const videoPlayers = {
    _players: {},

    _playersPlaying: [], /* the players that are currently playing videos, if any  */

    setPlayer: function setPlayer(lensId, player) {
        // store a player object

        const logHdr = 'videoPlayers.setPlayer: ';
        log(logHdr + 'enter');
        log(logHdr + 'lensId=' + lensId);

        this._players[lensId] = player;
        // store a reference to the player

        log(logHdr + 'leave');
    },

    getPlayer: function getPlayer(lensId) {
        // return a player object

        const logHdr = 'videoPlayers.getPlayer: ';
        log(logHdr + 'enter');
        log(logHdr + 'lensId=' + lensId);

        const player = this._players[lensId];
        // get a reference to the player, or undefined if not stored

        log(logHdr + 'leave');
        return player;
    },

    isVideoPlaying: function isVideoPlaying(lensId) {
        const logHdr = 'videoPlayers.isVideoPlaying: ';
        log(logHdr + 'enter');
        log(logHdr + 'lensId=' + lensId);

        const playingVideos = this._playersPlaying;

        const count = playingVideos.length;
        // how many players are playing?

        log(logHdr + 'count=' + count);

        for (var zIndex = 0; zIndex < count; zIndex++) {
            // once for each player that is playing

            log(logHdr + 'processing player ' + zIndex + 1 + '/' + count);

            var player = playingVideos[zIndex];

            const elemId = player.element.id;
            // get the DOM element id of the current player object

            log(logHdr + 'elemId=' + elemId);

            var currLensId = elemIdUtils.getLensIdFromVideoIFrameElemId(elemId);
            // extract the lens id

            if (currLensId === lensId) {
                // if we found the target player

                log(logHdr + 'found the target player');
                log(logHdr + 'leave');
                return true;
            }
        }

        log(logHdr + 'did NOT find the target player');
        log(logHdr + 'leave');

        return false;
    },

    isAnyPlayerPlaying: function isAnyPlayerPlaying() {
        const logHdr = 'videoPlayers.isAnyPlayerPlaying: ';
        log(logHdr + 'enter');

        const count = this._playersPlaying.length;
        // how many players are playing?

        log(logHdr + 'count=' + count);

        const playing = (count > 0);

        log(logHdr + 'playing=' + playing);
        log(logHdr + 'leave');
        return playing;
    },

    setPlayerStopped: function setPlayerStopped(lensId) {
        // indicate that the specified player has stopped playing video

        const logHdr = 'videoPlayers.setPlayerStopped: ';
        log(logHdr + 'enter');
        log(logHdr + 'lensId=' + lensId);

        const anyPlaying = this.isAnyPlayerPlaying();
        // are any players recorded as playing?

        log(logHdr + 'anyPlaying=' + anyPlaying);

        if (!anyPlaying) {
            // if not

            log(logHdr + 'we do NOT have a record of any videos currently playing so we are done');
            log(logHdr + 'leave');
            return;
        }

        const count = this._playersPlaying.length;
        // how many players are playing?

        log(logHdr + 'count=' + count);

        for (var zIndex = 0; zIndex < count; zIndex++) {
            // once for each player that is playing

            log(logHdr + 'processing player ' + zIndex + 1 + '/' + count);

            var player = this._playersPlaying[zIndex];

            const elemId = player.element.id;
            // get the DOM element id of the current player object

            log(logHdr + 'elemId=' + elemId);

            var currLensId = elemIdUtils.getLensIdFromVideoIFrameElemId(elemId);
            // extract the lens id

            if (currLensId === lensId) {
                // if we found the target player

                log(logHdr + 'found the target player');

                this._playersPlaying.splice(zIndex, 1);
                // remove the player from the array

                log(logHdr + 'removed the target player from the array');
                log(logHdr + 'leave');
                return;
            }
        }

        log(logHdr + 'leave');
    },

    setPlayerPlaying: function setPlayerPlaying(lensId, player) {
        // indicate that the specified player is currently playing video

        const logHdr = 'videoPlayers.setPlayerPlaying: ';
        log(logHdr + 'enter');
        log(logHdr + 'lensId=' + lensId);

        if (player === null) {
            // if the caller passed a null player

            log(logHdr + 'caller passed a NULL player.  should NOT happen.');
            log(logHdr + 'leave');
            return;
        }

        const anyPlaying = this.isAnyPlayerPlaying();
        // are any other players playing?

        log(logHdr + 'anyPlaying=' + anyPlaying);

        if (anyPlaying) {
            // if so

            const playingCount = this._playersPlaying.length;
            // how many players are playing?

            log(logHdr + 'playingCount=' + playingCount);

            for (var zIndex = 0; zIndex < playingCount; zIndex++) {
                // once for each player that is playing

                var currPlayer = this._playersPlaying[zIndex];

                const elemId = eventPlayer.element.id;
                // get the DOM element id of the current player object

                var currLensId = elemIdUtils.getLensIdFromVideoIFrameElemId(elemId);
                // extract the lens id

                if (currLensId === lensId) {
                    // if the specified video is already in the list

                    log(logHdr + 'the specified lens is ALREADY in the list of playing videos, so we are done');
                    log(logHdr + 'leave');
                    return;
                }
            }
        }
        else {
            // if none playing

            log(logHdr + 'there are no other videos currently playing so we do NOT have to check whether the target video is already in the list of playing videos');
        }

        log(logHdr + 'atc this._playersPlaying.push');

        this._playersPlaying.push(player);
        // add the player to the list of playing videos

        log(logHdr + 'bf this._playersPlaying.push');

        log(logHdr + 'added the lens to the list of playing videos');
        log(logHdr + 'leave');
    },

    stopPlayingVideosExcept: function stopPlayingVideosExcept(lensId) {
        // stop playing any videos that are currently playing

        const logHdr = 'videoPlayers.stopPlayingVideosExcept: ';
        log(logHdr + 'enter');
        log(logHdr + 'lensId=' + lensId);

        const anyPlaying = this.isAnyPlayerPlaying();
        // are any players playing?

        log(logHdr + 'anyPlaying=' + anyPlaying);

        if (!anyPlaying) {
            // if not

            log(logHdr + 'no videos are currently playing, so we are done');
            log(logHdr + 'leave');
            return;
        }

        // if at least one video is currently playing

        var playersCopy = this._playersPlaying.slice(0);
        // clone the array of playing players

        this._playersPlaying = [];
        // clear the array of playing players
        // not perfect code, but should reduce the chances of concurrency errors

        log(logHdr + 'cloned _playersPlaying and cleared the _playersPlaying property value');

        const playingCount = playersCopy.length;
        // how many players are playing?

        log(logHdr + 'playingCount=' + playingCount);

        var skippedPlayer = null;

        for (var zIndex = 0; zIndex < playingCount; zIndex++) {
            // once for each player that is playing

            log(logHdr + 'processing player ' + (zIndex + 1) + '/' + playingCount);

            var player = playersCopy[zIndex];

            const currElemId = player.element.id;
            // get the DOM element id of the Player object

            log(logHdr + 'currElemId=' + currElemId);

            const currLensId = elemIdUtils.getLensIdFromVideoIFrameElemId(currElemId);
            // get the lens id from the iFrame DOM element id

            if (currLensId === lensId) {
                // if this is the lens to skip

                log(logHdr + 'this is the lens to skip, so we save a reference to it');

                skippedPlayer = player;
                // save a reference to it
            }
            else {
                // if not the player to skip

                log(logHdr + 'atc player.pause');

                player.pause();
                // stop the video

                log(logHdr + 'bf player.pause');
            }
        }

        if (skippedPlayer !== null) {
            // if we saved a player reference

            log(logHdr + 'adding the skipped player to the empty list of playing videos');

            this._playersPlaying.push(skippedPlayer);
            // append the skipped player to the list of playing videos
        }

        log(logHdr + 'leave');
    }
};