# Source: add-text-track-data.js

    /**
     * @file add-text-track-data.js
     */
    import window from 'global/window';
    import videojs from 'video.js';
    /**
     * Define properties on a cue for backwards compatability,
     * but warn the user that the way that they are using it
     * is depricated and will be removed at a later date.
     *
     * @param {Cue} cue the cue to add the properties on
     * @private
     */
    const deprecateOldCue = function(cue) {
      Object.defineProperties(cue.frame, {
        id: {
          get() {
            videojs.log.warn(
              'cue.frame.id is deprecated. Use cue.value.key instead.'
            );
            return cue.value.key;
          }
        },
        value: {
          get() {
            videojs.log.warn(
              'cue.frame.value is deprecated. Use cue.value.data instead.'
            );
            return cue.value.data;
          }
        },
        privateData: {
          get() {
            videojs.log.warn(
              'cue.frame.privateData is deprecated. Use cue.value.data instead.'
            );
            return cue.value.data;
          }
        }
      });
    };

    const durationOfVideo = function(duration) {
      let dur;

      if (isNaN(duration) || Math.abs(duration) === Infinity) {
        dur = Number.MAX_VALUE;
      } else {
        dur = duration;
      }
      return dur;
    };
    /**
     * Add text track data to a source handler given the captions and
     * metadata from the buffer.
     *
     * @param {Object} sourceHandler the flash or virtual source buffer
     * @param {Array} captionArray an array of caption data
     * @param {Array} metadataArray an array of meta data
     * @private
     */
    const addTextTrackData = function(sourceHandler, captionArray, metadataArray) {
      let Cue = window.WebKitDataCue || window.VTTCue;

      if (captionArray) {
        captionArray.forEach(function(caption) {
          let track = caption.stream;

          this.inbandTextTracks_[track].addCue(
            new Cue(
              caption.startTime + this.timestampOffset,
              caption.endTime + this.timestampOffset,
              caption.text
            ));
        }, sourceHandler);
      }

      if (metadataArray) {
        let videoDuration = durationOfVideo(sourceHandler.mediaSource_.duration);

        metadataArray.forEach(function(metadata) {
          let time = metadata.cueTime + this.timestampOffset;

          metadata.frames.forEach(function(frame) {
            let cue = new Cue(
              time,
              time,
              frame.value || frame.url || frame.data || '');

            cue.frame = frame;
            cue.value = frame;
            deprecateOldCue(cue);

            this.metadataTrack_.addCue(cue);
          }, this);
        }, sourceHandler);

        // Updating the metadeta cues so that
        // the endTime of each cue is the startTime of the next cue
        // the endTime of last cue is the duration of the video
        if (sourceHandler.metadataTrack_ &&
            sourceHandler.metadataTrack_.cues &&
            sourceHandler.metadataTrack_.cues.length) {
          let cues = sourceHandler.metadataTrack_.cues;
          let cuesArray = [];

          // Create a copy of the TextTrackCueList...
          // ...disregarding cues with a falsey value
          for (let i = 0; i < cues.length; i++) {
            if (cues[i]) {
              cuesArray.push(cues[i]);
            }
          }

          // Group cues by their startTime value
          let cuesGroupedByStartTime = cuesArray.reduce((obj, cue) => {
            let timeSlot = obj[cue.startTime] || [];

            timeSlot.push(cue);
            obj[cue.startTime] = timeSlot;

            return obj;
          }, {});

          // Sort startTimes by ascending order
          let sortedStartTimes = Object.keys(cuesGroupedByStartTime)
                                       .sort((a, b) => Number(a) - Number(b));

          // Map each cue group's endTime to the next group's startTime
          sortedStartTimes.forEach((startTime, idx) => {
            let cueGroup = cuesGroupedByStartTime[startTime];
            let nextTime = Number(sortedStartTimes[idx + 1]) || videoDuration;

            // Map each cue's endTime the next group's startTime
            cueGroup.forEach((cue) => {
              cue.endTime = nextTime;
            });
          });
        }
      }
    };

    export default {
      addTextTrackData,
      durationOfVideo
    };