define(['jquery', 'core/eventifier', 'ui/mediaplayer/support', 'ui/mediaplayer/youtubeManager', 'handlebars', 'lib/handlebars/helpers'], function ($$1, eventifier, support, youtubeManagerFactory, Handlebars, Helpers0) { 'use strict';

    $$1 = $$1 && Object.prototype.hasOwnProperty.call($$1, 'default') ? $$1['default'] : $$1;
    eventifier = eventifier && Object.prototype.hasOwnProperty.call(eventifier, 'default') ? eventifier['default'] : eventifier;
    support = support && Object.prototype.hasOwnProperty.call(support, 'default') ? support['default'] : support;
    youtubeManagerFactory = youtubeManagerFactory && Object.prototype.hasOwnProperty.call(youtubeManagerFactory, 'default') ? youtubeManagerFactory['default'] : youtubeManagerFactory;
    Handlebars = Handlebars && Object.prototype.hasOwnProperty.call(Handlebars, 'default') ? Handlebars['default'] : Handlebars;
    Helpers0 = Helpers0 && Object.prototype.hasOwnProperty.call(Helpers0, 'default') ? Helpers0['default'] : Helpers0;

    if (!Helpers0.__initialized) {
      Helpers0(Handlebars);
      Helpers0.__initialized = true;
    }
    var Template = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
      this.compilerInfo = [4,'>= 1.0.0'];
    helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
      var buffer = "", stack1, helper, functionType="function", escapeExpression=this.escapeExpression;


      buffer += "<div class=\"media video youtube\" data-video-src=\"";
      if (helper = helpers.src) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.src); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + "\" data-video-id=\"";
      if (helper = helpers.id) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.id); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + "\" data-type=\"youtube\"></div>\n";
      return buffer;
      });
    function youtubeTpl(data, options, asString) {
      var html = Template(data, options);
      return (asString || true) ? html : $(html);
    }

    /**
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * as published by the Free Software Foundation; under version 2
     * of the License (non-upgradable).
     *
     * 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 General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with this program; if not, write to the Free Software
     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
     *
     * Copyright (c) 2015-2021 (original work) Open Assessment Technologies SA ;
     */

    /**
     * The polling interval used to update the progress bar while playing a YouTube video.
     * Note : the YouTube API does not provide events to update this progress bar...
     * @type {Number}
     */
    const youtubePolling = 100;

    /**
     * List of YouTube events that can be listened to for debugging
     * @type {String[]}
     */
    const youtubeEvents = ['onApiChange', 'onError', 'onPlaybackQualityChange', 'onPlaybackRateChange', 'onStateChange'];

    /**
     * List of player events that can be listened to for debugging
     * @type {String[]}
     */
    const playerEvents = ['end', 'error', 'pause', 'play', 'ready', 'resize', 'timeupdate'];

    /**
     * A local manager for Youtube players.
     * Relies on https://developers.google.com/youtube/iframe_api_reference
     * @type {Object}
     */
    const youtubeManager = youtubeManagerFactory();

    /**
     * Defines a player object dedicated to youtube media
     * @param {jQuery} $container - Where to render the player
     * @param {Object} config - The list of config entries
     * @param {Array} config.sources - The list of media sources
     * @param {Boolean} [config.debug] - Enables the debug mode
     * @param {Number} [config.polling=100] - The polling interval used to update the progress bar while playing a YouTube video.
     * @returns {Object} player
     */
    function youtubePlayerFactory($container) {
      let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      const sources = config.sources || [];
      const source = sources[0] || {};
      const otherSources = sources.slice(1);
      config.polling = config.polling || youtubePolling;
      let $media;
      let media;
      let interval;
      let destroyed;
      let initWidth;
      let initHeight;
      let callbacks = [];

      // eslint-disable-next-line
      const debug = function (action) {
        for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
          args[_key - 1] = arguments[_key];
        }
        return config.debug && window.console.log(`[youtube:${action}]`, ...args);
      };
      const queueMedia = (url, register) => {
        const id = youtubeManager.extractYoutubeId(url);
        if (id) {
          if (media) {
            register(id);
          } else {
            callbacks.push(() => register(id));
          }
          return true;
        }
        return false;
      };
      const player = {
        init() {
          $media = $$1(youtubeTpl({
            src: source.src,
            id: youtubeManager.extractYoutubeId(source.src)
          }));
          $container.append($media);
          otherSources.forEach(otherSource => this.addMedia(otherSource.src));
          media = null;
          destroyed = false;
          youtubeManager.add($media, this, {
            controls: !support.canControl()
          });
          return true;
        },
        onReady(event) {
          media = event.target;
          $media = $$1(media.getIframe()); // the injected media placeholder is replaced by an iframe by the YouTube lib

          if (!destroyed) {
            // install debug logger
            if (config.debug) {
              debug('installed', media);
              youtubeEvents.forEach(eventName => media.addEventListener(eventName, e => {
                debug('media event', eventName, $media && $media.data('videoSrc'), e);
              }));
              playerEvents.forEach(eventName => {
                this.on(eventName, function () {
                  for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
                    args[_key2] = arguments[_key2];
                  }
                  debug('player event', eventName, $media && $media.data('videoSrc'), ...args);
                });
              });
            }
            if (initWidth && initHeight) {
              this.setSize(initWidth, initHeight);
            }
            callbacks.forEach(cb => cb());
            callbacks = [];
            this.trigger('ready');
          } else {
            this.destroy();
          }
        },
        onStateChange(event) {
          this.stopPolling();
          if (!destroyed) {
            switch (event.data) {
              // ended
              case 0:
                this.trigger('end');
                break;

              // playing
              case 1:
                this.trigger('play');
                this.startPolling();
                break;

              // paused
              case 2:
                this.trigger('pause');
                break;
            }
          }
        },
        stopPolling() {
          if (interval) {
            window.clearInterval(interval);
            interval = null;
          }
        },
        startPolling() {
          interval = window.setInterval(() => this.trigger('timeupdate'), config.polling);
        },
        destroy() {
          debug('api call', 'destroy');
          destroyed = true;
          this.stopPolling();
          this.removeAllListeners();
          if (media) {
            youtubeEvents.forEach(ev => media.removeEventListener(ev));
            media.destroy();
            media = void 0;
          } else {
            youtubeManager.remove($media, this);
          }
          if ($media) {
            $media.remove();
            $media = void 0;
          }
        },
        getMedia() {
          debug('api call', 'getMedia', media);
          return media;
        },
        getPosition() {
          let position = 0;
          if (media) {
            position = media.getCurrentTime();
          }
          debug('api call', 'getPosition', position);
          return position;
        },
        getDuration() {
          let duration = 0;
          if (media) {
            duration = media.getDuration();
          }
          debug('api call', 'getDuration', duration);
          return duration;
        },
        getVolume() {
          let volume = 0;
          if (media) {
            volume = media.getVolume();
          }
          debug('api call', 'getVolume', volume);
          return volume;
        },
        setVolume(volume) {
          debug('api call', 'setVolume', volume);
          if (media) {
            media.setVolume(parseFloat(volume));
          }
        },
        setSize(width, height) {
          debug('api call', 'setSize', width, height);
          this.trigger('resize', width, height);
          if (!media) {
            initWidth = width;
            initHeight = height;
          }
        },
        seek(time) {
          debug('api call', 'seek', time);
          if (media) {
            media.seekTo(parseFloat(time), true);
          }
        },
        play() {
          debug('api call', 'play');
          if (media) {
            media.playVideo();
          }
        },
        pause() {
          debug('api call', 'pause');
          if (media) {
            media.pauseVideo();
          }
        },
        stop() {
          debug('api call', 'stop');
          if (media) {
            media.stopVideo();
            this.trigger('end');
          }
        },
        mute(state) {
          debug('api call', 'mute', state);
          if (media) {
            media[state ? 'mute' : 'unMute']();
          }
        },
        isMuted() {
          let mute = false;
          if (media) {
            mute = media.isMuted();
          }
          debug('api call', 'isMuted', mute);
          return mute;
        },
        addMedia(url) {
          debug('api call', 'addMedia', url);
          return queueMedia(url, id => media && media.cueVideoById(id));
        },
        setMedia(url) {
          debug('api call', 'setMedia', url);
          callbacks = [];
          return queueMedia(url, id => media && media.loadVideoById(id));
        }
      };
      return eventifier(player);
    }

    return youtubePlayerFactory;

});
