# JSDoc: Source: app/channel/media/queuedMedia.js

# Source: app/channel/media/queuedMedia.js

    /*Canopy - The next generation of stoner streaming software
    Copyright (C) 2024-2025 Rainbownapkin and the TTN Community

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.*/

    //Local Imports
    const media = require('./media');

    /**
     * Class extending media which represents a queued piece of media
     * @extends media
     */
    module.exports = class extends media{
        /**
         * Creates a new queued media object
         * @param {Number} startTime - JS Epoch representing start time
         * @param {Number} startTimeStamp - Media start time stamp in seconds (relative to duration)
         * @param {Number} earlyEnd - Media end timestamp in seconds (relative to duration)
         * @param {String} uuid - Media object's unique identifier
         */
        constructor(title, fileName, url, id, type, duration, rawLink, startTime, startTimeStamp = 0, earlyEnd, uuid){
            //Call derived constructor
            super(title, fileName, url, id, type, duration, rawLink);
            //Set media start time
            this.startTime = startTime;
            //Set the media start time stamp
            this.startTimeStamp = startTimeStamp;
            //Create empty variable to hold early end if media is stopped early
            this.earlyEnd = earlyEnd;
            //Set status for discriminator key
            this.status = 'queued';

            //If we have a null uuid (can't use default argument because of 'this')
            if(uuid == null){
                //Generate id unique to this specific entry of this specific file within this specific channel's queue
                //That way even if we have six copies of the same video queued, we can still uniquely idenitify each instance
                this.genUUID();
            }else{
                this.uuid = uuid;
            }
        }

        //statics
        /**
         * Creates a queuedMedia object from a media object
         * @param {media} media - Media object to queue
         * @param {Number} startTime - Start time formatted as a JS Epoch
         * @param {Number} startTimeStamp - Start time stamp in seconds
         * @returns {queuedMedia} queuedMedia object created from given media object
         */
        static fromMedia(media, startTime, startTimeStamp){
            //Create and return queuedMedia object from given media object and arguments
            return new this(
                media.title,
                media.fileName,
                media.url,
                media.id,
                media.type,
                media.duration,
                media.rawLink,
                startTime,
                startTimeStamp);
        }

        /**
         * Converts array of media objects into array of queuedMedia objects
         * @param {Array} mediaList - Array of media objects to queue
         * @param {Number} start - Start time formatted as JS Epoch
         * @returns Array of converted queued media objects
         */
        static fromMediaArray(mediaList, start){
            //Queued Media List
            const queuedMediaList = [];
            //Start Time Offset
            let startOffset = 0;

            for(let media of mediaList){
                //Convert mediaObj to queuedMedia and push to the back of the list
                queuedMediaList.push(this.fromMedia(media, start + startOffset, 0));

                //Set start offset to end of the current item
                startOffset += (media.duration * 1000) + 5;
            }

            return queuedMediaList;
        }

        //methods
        /**
         * Generates new unique identifier for queued media
         */
        genUUID(){
            this.uuid = crypto.randomUUID();
        }

        /**
         * return the end time of a given queuedMedia object
         * @param {boolean} fullTime - Overrides early ends
         * @returns end time of given queuedMedia object
         */
        getEndTime(fullTime = false){
            //If we have an early ending
            if(this.earlyEnd == null || fullTime){
                //Calculate our ending
                return this.startTime + ((this.duration - this.startTimeStamp) * 1000);
            }else{
                //Return our early end
                return this.startTime + (this.earlyEnd * 1000);
            }
        }
    }