import is from '@pluginjs/is';
import templateEngine from '@pluginjs/template';
import { eventable, register, stateable, styleable } from '@pluginjs/pluginjs';
import Component from '@pluginjs/component';

var _extends = Object.assign || function (target) {
  for (var i = 1; i < arguments.length; i++) {
    var source = arguments[i];

    for (var key in source) {
      if (Object.prototype.hasOwnProperty.call(source, key)) {
        target[key] = source[key];
      }
    }
  }

  return target;
};
function nub(arr) {
  return Array.from(new Set(arr));
}
function isPlainObject(data) {
  if (typeof data !== 'object') {
    return false;
  }

  if (data === null) {
    return false;
  }

  if (data instanceof Set || data instanceof Map) {
    return false;
  }

  if (Array.isArray(data)) {
    return false;
  }

  return true;
}
function deepMergeTwo(x, y) {
  if (isPlainObject(y) && isPlainObject(x) || isPlainObject(x) && Array.isArray(y)) {
    return fromPairs$1(nub(Object.keys(x).concat(Object.keys(y))).map(key => [key, deepMergeTwo(x[key], y[key])]));
  }

  if (isPlainObject(y) && typeof x === 'function') {
    return Object.assign(function (...args) {
      return x.apply(this, args);
    }, y);
  }

  if (isPlainObject(y) && Array.isArray(x)) {
    return Object.assign([], x, y);
  }

  if (isPlainObject(x) && typeof y === 'function') {
    return Object.assign(function (...args) {
      return y.apply(this, args);
    }, x);
  }

  if (Array.isArray(y) && Array.isArray(x)) {
    // return x.concat(y)
    return nub(Object.keys(y).concat(Object.keys(x))).map(index => deepMergeTwo(x[index], y[index]));
  }

  if (typeof y === 'undefined') {
    return x;
  }
  return y;
}
function isObject(obj) {
  return Object(obj) === obj;
}
function deepMerge(...args) {
  return args.filter(isObject).reduce(deepMergeTwo);
}

const curry = (fn, args = []) => (...subArgs) => {
  const currylen = fn.currylen || fn.length;
  const collect = args.concat(subArgs);
  if (collect.length >= currylen) {
    return fn(...collect);
  }
  return curry(fn, collect);
};

const compose = (...fn) => {
  const callback = (...args) => fn.reduceRight((r, i, index) => {
    if (Array.isArray(r) && index === fn.length - 1) {
      return i(...r);
    }
    return i(r);
  }, args);
  callback.currylen = fn[fn.curylen || fn.length - 1].length;
  return callback;
};

function fromPairs$1(arr) {
  return arr.reduce((r, [k, v]) => _extends({}, r, {
    [k]: v
  }), {});
}

// last:: [a] -> a

// compose(
//   append(parent),
//   addClass('foo')
// )(el)

// compose(append(parent), addClass('foo'), ...)
// let c = append(parent).addClass('foo').fn$fn, fn

// let el = document.createElement('div')
//   |> addClass('foo')
//   |> append(parent)

// addclass()
//   .remove()
//   .append()

// addClass(el, ...args)

// addClass(...args, el)
// addClass('foo','bar')

/**
 * setStyle({
 *  fontSize: '16px',
 *  display: 'flex'
 * }, element)
 */
const setStyle = curry((style, el) => {
  Object.entries(style).forEach(([k, v]) => {
    if (typeof v === 'number') {
      v = `${v.toString()}px`;
    }
    el.style[k] = v;
  });
  return el;
});

const query = (selector, parent = document) => parent.querySelector(selector);

const html = curry((content, el) => {
  el.innerHTML = content;
  return el;
});

const children = el => Array.from(el.children);

const parent = el => el.parentNode;
// 解析 HTML/SVG/XML 字符串
const parseHTML = (...args) => {
  const htmlString = Array.isArray(args[0]) ? args[0].reduce((result, str, index) => result + args[index] + str) : args[0];
  const childNodes = compose(children, html(htmlString))(document.createElement('div'));
  if (childNodes.length === 1) {
    return childNodes[0];
  }
  return childNodes;
};

const append = curry((child, el) => {
  if (is.string(child)) {
    el.insertAdjacentHTML('beforeend', child);
  } else {
    el.append(child);
  }
  return el;
});

const namespace = 'video';

const events = {
  READY: 'ready',
  DESTROY: 'destroy',
  LOAD: 'load',
  LOADED: 'loaded',
  PLAY: 'play',
  PAUSE: 'pause',
  STOP: 'stop',
  PLAYEND: 'playend',
  PLAYERR: 'playerr'
};

const classes = {
  NAMESPACE: `pj-${namespace}`,
  THEME: '{namespace}--{theme}',
  POSTER: '{namespace}-poster'
};

const methods = ['enable', 'disable', 'destroy', 'pause', 'load', 'play', 'stop', 'volume', 'setSize', 'switchVideo', 'duration', 'currentTime', 'mute', 'unMute', 'setCurrentTime'];

const defaults = {
  template() {
    return '<div class="{classes.NAMESPACE}">' + '{poster}' + '</div>';
  },
  templates: {
    poster() {
      return '<div class="{classes.POSTER}"></div>';
    }
  },
  url: '',
  id: '',
  type: '',
  autoplay: true,
  loop: true,
  controls: false,
  poster: ''
};

const info = { version: '0.0.1' };

let Html5 = class Html5 {
  constructor(video, element, options) {
    this.element = element;
    this.options = options;
    this.instance = video;
    this.classes = video.classes;
  }

  load() {
    this.wrap = parseHTML(this.createHtml());
    append(this.wrap, this.element);
    if (this.options.poster) {
      this.poster = query(`.${this.instance.classes.POSTER}`, this.wrap);
      setStyle({ 'background-image': `url(${this.options.poster})` }, this.poster);
    }

    this.video = document.createElement('video');
    this.setDefaultParameters();
    append(this.video, this.wrap);

    this.instance.trigger(events.LOAD);
    this.instance.trigger(events.LOADED);
    if (this.options.poster) {
      this.poster.style.display = 'none';
    }
    this.bind();
  }

  setDefaultParameters() {
    if (is.array(this.options.url)) {
      for (let i = 0; i < this.options.url.length; i++) {
        const videoTypeArr = this.options.url[i].split('.');
        const videoType = videoTypeArr[videoTypeArr.length - 1];

        this.addSourceToVideo(this.options.url[i], videoType);
      }
    } else {
      const videoTypeArr = this.options.url.split('.');
      const videoType = videoTypeArr[videoTypeArr.length - 1];

      this.addSourceToVideo(this.options.url, videoType);
    }

    this.video.autoplay = this.options.autoplay;
    this.video.controls = this.options.controls;
    this.video.loop = this.options.loop;
  }

  createHtml() {
    let poster = '';

    if (this.options.poster !== '') {
      poster = templateEngine.render(this.options.templates.poster.call(this), {
        classes: this.classes
      });
    }

    const html$$1 = templateEngine.render(this.options.template.call(this), {
      classes: this.classes,
      poster
    });
    return html$$1;
  }

  addSourceToVideo(src, type) {
    const source = document.createElement('source');

    source.src = src;
    source.type = `video/${type}`;

    append(source, this.video);
  }

  setSize(width, height) {
    setStyle({
      width,
      height
    }, this.wrap);
  }

  switchVideo(id) {
    this.video.src = id;
  }

  bind() {
    this.eventListener('play');
    this.eventListener('pause');
    this.eventListener('error');
    // this.eventListener('stalled')
  }

  registerEvent(eventName, callback, element) {
    if (!this.listeners) {
      this.listeners = {};
    }

    if (!this.listeners[eventName]) {
      this.listeners[eventName] = [];
    }

    this.listeners[eventName].push(callback);

    element.addEventListener(eventName, callback);
  }

  removeListener(eventName, element) {
    if (!this.listeners[eventName]) {
      console.log('not bind eventName:', eventName);
    }

    this.listeners[eventName].map(callback => {
      element.removeEventListener(eventName, callback);
    });
  }

  unbind() {
    this.removeListener('error', this.video);
    this.removeListener('play', this.video);
    this.removeListener('pause', this.video);
  }

  eventListener(eventName) {
    const capitalEvent = eventName.toUpperCase();
    this.registerEvent(eventName, () => {
      this.instance.trigger(events[capitalEvent]);
    }, this.video);
  }

  currentTime() {
    return this.video.currentTime;
  }

  duration() {
    return this.video.duration;
  }

  setCurrentTime(val) {
    this.video.currentTime = val;
  }

  pause() {
    this.video.pause();
  }

  play() {
    this.video.play();
  }

  mute() {
    this.video.muted = true;
  }

  unMute() {
    this.video.muted = false;
  }

  stop() {
    this.video.currentTime = 0;
    this.video.pause();
    this.instance.trigger(events.STOP);
  }

  volume(value) {
    this.video.volume = value / 100;
  }

  destroy() {
    this.unbind();
    const element = query('video', this.wrap);
    if (element) {
      element.src = '//about:blank';
    }
    this.wrap.remove();
  }
};

const outputIdentity = identity => {
  if (!identity) {
    return { type: 'self', value: '' };
  }
  if (typeof identity === 'string') {
    return { type: 'selector', value: identity };
  }

  return identity;
};

const tupleToStyleSelector = (tuple, prefix) => {
  if (typeof tuple === 'string') {
    return tuple;
  }
  return Object.entries(tuple).map(kv => `[${prefix}${kv.join('=')}]`).join('');
};

const dispatch = event => {
  const { target, currentTarget } = event;
  const eventStorage = EventStorage.getEventStorage(currentTarget);
  const eventName = event.type;

  const attrVerify$$1 = {
    self: node => node === currentTarget,
    class: (node, value) => node.matches(`.${value}`),
    selector: (node, value) => node.matches(value),
    id: (node, value) => node.matches(`#${value}`),
    tagName: (node, value) => node.matches(value),
    dom: (node, value) => node === value,
    dataset: (node, value) => node.matches(tupleToStyleSelector(value, 'data-')),
    attribute: (node, value) => node.matches(tupleToStyleSelector(value)),
    func: (node, value) => Boolean(value(node))
  };

  const nodeTreeCheck = (node, result = []) => {
    if (!currentTarget.contains(node)) {
      return result;
    }

    const matchEventList = eventStorage.listeners[eventName].filter(({ identity }) => {
      const { type, value } = identity;
      const identityMapper = attrVerify$$1[type];
      if (identityMapper && identityMapper(node, value)) {
        return true;
      }
      return false;
    });
    return nodeTreeCheck(parent(node), result.concat(matchEventList));
  };
  // nodeTreeCheck(target).map(e => console.log(e.handler.toString()))
  nodeTreeCheck(target).reduce((result, { handler }) => result !== false && handler(event), true);
};

let EventStorage = class EventStorage {
  constructor(element) {
    this.element = element;
    this.listeners = {};
  }

  on({ identity, handler, eventName, namespace }) {
    this.ensureHandler(handler);

    if (!this.hasListeners(eventName)) {
      this.createEventListener(eventName);
    }

    if (this.checkRepeats(eventName, handler)) {
      return;
    }

    this.listeners[eventName].push({ identity, handler, namespace });
  }

  once({ identity, handler, eventName, namespace }) {
    this.ensureHandler(handler);

    if (!this.hasListeners(eventName)) {
      this.createEventListener(eventName);
    }

    const callback = event => {
      this.removeListener(eventName, callback);

      return handler(event);
    };

    this.listeners[eventName].push({ identity, handler: callback, namespace });
  }

  off(_eventName, handler) {
    if (typeof handler === 'undefined') {
      return this.removeAllListeners(_eventName);
    }
    return this.removeListener(_eventName, handler);
  }

  trigger(eventName, data) {
    const event = new CustomEvent(eventName, {
      detail: data
    });
    this.element.dispatchEvent(event);
  }

  clear() {
    Object.entries(this.listeners).map(([key, value]) => {
      this.deleteEventListener(key);
    });

    this.listener = {};
  }

  removeListener(_eventName, handler) {
    const [eventName, namespace] = _eventName.split('.');
    //   .example  || click  || click.example
    if (!eventName && namespace) {
      Object.entries(this.listeners).map(([key, value]) => {
        this.listeners[key] = this.listeners[key].filter(eventTuple => eventTuple.handler !== handler || eventTuple.namespace !== namespace);

        if (this.listeners[key].length === 0) {
          this.deleteEventListener(key);
        }
      });
    } else if (eventName && !namespace) {
      // console.log('eventName')
      this.listeners[eventName] = this.listeners[eventName].filter(eventTuple => eventTuple.handler !== handler);

      if (this.listeners[eventName].length === 0) {
        this.deleteEventListener(eventName);
      }
    } else if (eventName && namespace) {
      this.listeners[eventName] = this.listeners[eventName].filter(eventTuple => eventTuple.handler !== handler || eventTuple.namespace !== namespace);

      if (this.listeners[eventName].length === 0) {
        this.deleteEventListener(eventName);
      }
    }
  }

  removeAllListeners(_eventName) {
    const [eventName, namespace] = _eventName.split('.');
    //   .example  || click  || click.example
    if (!eventName && namespace) {
      Object.entries(this.listeners).map(([key, value]) => {
        this.listeners[key] = this.listeners[key].filter(eventTuple => eventTuple.namespace !== namespace);

        if (this.listeners[key].length === 0) {
          this.deleteEventListener(key);
        }
      });
    } else if (eventName && !namespace) {
      this.deleteEventListener(eventName);
    } else if (eventName && namespace && this.listeners[eventName]) {
      this.listeners[eventName] = this.listeners[eventName].filter(eventTuple => eventTuple.namespace !== namespace);

      if (this.listeners[eventName].length === 0) {
        this.deleteEventListener(eventName);
      }
    }

    return this;
  }

  createEventListener(eventName) {
    this.listeners[eventName] = [];
    this.element.addEventListener(eventName, dispatch, false);
  }

  deleteEventListener(eventName) {
    this.element.removeEventListener(eventName, dispatch);
    delete this.listeners[eventName];
  }

  checkRepeats(eventName, handler) {
    return this.listeners[eventName].filter(value => value.handler === handler).length !== 0;
  }

  hasListeners(eventName) {
    if (!this.listeners[eventName] || Object.keys(this.listeners[eventName]).length === 0) {
      return false;
    }

    return true;
  }

  ensureHandler(handler) {
    const type = typeof handler;
    if (type === 'function') {
      return handler;
    }
    throw new TypeError(`Listeners should be function or closure. Received type: ${type}`);
  }

  static of({ type: _eventName, identity, handler }, element) {
    if (!element.__eventStorage) {
      element.__eventStorage = new this(element);
    }

    const [eventName, namespace] = _eventName.split('.');

    const eventStorage = this.getEventStorage(element);

    eventStorage.on({
      identity: outputIdentity(identity),
      handler,
      eventName,
      namespace
    });
  }

  static once({ type: _eventName, identity, handler }, element) {
    if (!element.__eventStorage) {
      element.__eventStorage = new this(element);
    }

    const [eventName, namespace] = _eventName.split('.');

    const eventStorage = this.getEventStorage(element);

    eventStorage.once({
      identity: outputIdentity(identity),
      handler,
      eventName,
      namespace
    });
  }

  static delete(options, element) {
    const eventStorage = this.getEventStorage(element);
    if (!eventStorage) {
      return;
    }

    const { type: _eventName = options, handler } = options;
    eventStorage.off(_eventName, handler);
  }

  static getEventStorage(element) {
    return element.__eventStorage;
  }
};

const trigger = curry((options, el) => {
  const { type = options, data } = options;
  const eventName = type;

  const eventStorage = EventStorage.getEventStorage(el);
  if (eventStorage && eventStorage.hasListeners(eventName)) {
    eventStorage.trigger(eventName, data);
  }

  return el;
});
/**
 * bindEvent ({
 *   type: 'example:CustomEvent',
 *   handler: event => {
 *     let { instance } = event.detail
 *   }
 * }, elemment)
 *
 * trigger({
 *   type: 'example:CustomEvent',
 *   data: {instance: this}
 * }, elemment)
 */

const bindEvent = curry((options, element) => {
  EventStorage.of(options, element);
  return element;
});

window.AsVimeoAPIReady = false;

let Vimeo = class Vimeo {
  constructor(instance, element, options) {
    this.element = element;
    this.options = options;
    this.instance = instance;
    this.classes = instance.classes;
  }

  load() {
    this.wrap = parseHTML(this.createHtml());
    append(this.wrap, this.element);
    if (this.options.poster) {
      this.poster = query(`.${this.instance.classes.POSTER}`, this.wrap);
      setStyle({ 'background-image': `url(${this.options.poster})` }, this.poster);
    }

    if (window.AsVimeoAPIReady) {
      this.init();
      this.instance.trigger(events.LOAD);
    } else {
      this.loadApi();
      bindEvent({
        type: 'AsVideoVimeoAPIReady',
        handler: () => {
          this.init();
          this.instance.trigger(events.LOAD);
        }
      }, this.element);
    }
  }

  init() {
    const playerSettings = {
      id: this.getId(),
      loop: this.options.loop,
      autoplay: this.options.autoplay,
      // height:400,
      // url:'https://player.vimeo.com/video/76979871',
      title: false, // defaults to true
      portrait: false, // Show the user’s portrait on the video. Defaults to true.
      // maxwidth: '',
      // maxheight '',
      xhtml: false, // Make the embed code XHTML compliant. Defaults to false.
      byline: false, // Show the byline on the video. Defaults to true.
      autopause: false // Pause this video automatically when another one plays. Defaults to true.
    };

    this.media = new window.Vimeo.Player(this.wrap, playerSettings);
    this.bind();
  }

  getId() {
    if (this.options.id) {
      return this.options.id;
    } else if (this.options.url) {
      return this.options.url.split('/')[3].split('?')[0];
    }
    return undefined;
  }

  createHtml() {
    let poster = '';

    if (this.options.poster !== '') {
      poster = templateEngine.render(this.options.templates.poster.call(this), {
        classes: this.classes
      });
    }

    const html$$1 = templateEngine.render(this.options.template.call(this), {
      classes: this.classes,
      poster
    });
    return html$$1;
  }

  loadApi() {
    const tag = document.createElement('script');
    tag.src = 'https://player.vimeo.com/api/player.js';
    document.querySelector('body').appendChild(tag);

    let count = 1;
    const vimeoApiReady = setInterval(() => {
      if (count > 50) {
        clearInterval(vimeoApiReady);
        console.log('loadApi error');
        this.instance.destroy();
      }
      count++;
      if (typeof window.Vimeo === 'undefined') {
        return;
      }
      window.AsVimeoAPIReady = true;
      trigger('AsVideoVimeoAPIReady', this.element);
      clearInterval(vimeoApiReady);
    }, 350);
  }

  bind() {
    this.media.on('play', () => {
      this.instance.trigger(events.PLAY);
    });
    this.media.on('pause', () => {
      this.instance.trigger(events.PAUSE);
    });
    this.media.on('loaded', () => {
      this.instance.trigger(events.LOADED);
      if (this.options.poster) {
        this.poster.style.display = 'none';
      }
    });
  }

  setSize(width, height) {
    setStyle({
      width,
      height
    }, this.wrap);
  }

  switchVideo(id) {
    this.media.loadVideo(id);
  }

  _currentTime() {
    this.media.getCurrentTime().then(seconds => {
      this.options.currentTime = seconds;
    });
  }

  currentTime() {
    this._currentTime();
    return this.options.currentTime;
  }

  _duration() {
    return this.media.getDuration().then(duration => {
      this.options.duration = duration;
    });
  }

  duration() {
    this._duration();
    return this.options.duration;
  }

  setCurrentTime(val) {
    this.media.setCurrentTime(val);
  }

  stop() {
    this.media.setCurrentTime(0);
    this.media.pause();
    this.instance.trigger(events.STOP);
  }

  mute() {
    this.volume(0);
  }

  unMute() {
    this.volume(50);
  }

  pause() {
    this.media.pause();
    this.instance.trigger('pause');
  }

  volume(value) {
    this.media.setVolume(value / 100);
  }

  play() {
    this.media.play();
  }

  destroy() {
    const element = query('iframe', this.wrap);
    if (element) {
      element.src = '//about:blank';
    }
    this.wrap.remove();
  }
};

window.AsYTAPIReady = false;

let Youtube = class Youtube {
  constructor(instance, element, options) {
    this.element = element;
    this.options = options;
    this.instance = instance;
    this.classes = instance.classes;
  }

  load() {
    this.wrap = parseHTML(this.createHtml());
    append(this.wrap, this.element);
    if (this.options.poster) {
      this.poster = query(`.${this.instance.classes.POSTER}`, this.wrap);
      setStyle({ 'background-image': `url(${this.options.poster})` }, this.poster);
    }

    if (window.AsYTAPIReady) {
      this.init();
      this.instance.trigger(events.LOAD);
    } else {
      this.loadApi();
    }
  }

  init() {
    this.iframe = document.createElement('div');
    append(this.iframe, this.wrap);

    this.setdefault();

    const playerSettings = {
      volume: 0, // 0 - 100
      autohide: 0, // autohide controls
      autoplay: this.options.autoplay, // autoplay on load
      color: 'red', // red, white
      controls: this.options.controls, // show control UI
      disablekb: 0, // enable/disable keyboard control
      enablejsapi: 1,
      fs: 0, // display fullscreen button
      hl: null, // interface language
      // iv_load_policy: 3,
      loop: 1, // loop video flag (doesn't work properly)
      modestbranding: 1, // show/hide youtube logo
      playsinline: 0,
      rel: 0, // shows relative videos
      showinfo: 0,
      start: 0, // set beginning of the video
      end: 0, // set end of the video
      quality: 'default' // small, medium, large, hd720, hd1080, highres or default
    };

    this.media = new YT.Player(this.iframe, {
      videoId: this.getId(),
      mute: true,
      repeat: true,
      playButtonClass: 'YTPlayer-play',
      pauseButtonClass: 'YTPlayer-pause',
      muteButtonClass: 'YTPlayer-mute',
      volumeUpClass: 'YTPlayer-volume-up',
      volumeDownClass: 'YTPlayer-volume-down',
      start: 0,
      pauseOnScroll: false,
      fitToBackground: true,
      playerVars: playerSettings,
      events: {
        onReady: () => {
          this.instance.trigger(events.LOADED);
          if (this.options.poster) {
            this.poster.style.display = 'none';
          }
        }
      }
    });
    this.bind();
  }

  getId() {
    if (this.options.id) {
      return this.options.id;
    } else if (this.options.url) {
      return this.options.url.split('/')[3].split('?v=')[1];
    }
    return undefined;
  }

  loadApi() {
    window.onYouTubeIframeAPIReady = () => {
      this.init();
      window.AsYTAPIReady = true;
      this.instance.trigger(events.LOAD);
    };

    const tag = document.createElement('script');
    tag.src = 'https://www.youtube.com/iframe_api';
    const firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  }

  setdefault() {
    this.options.autoplay = this.options.autoplay ? 1 : 0;
    this.options.controls = this.options.controls ? 1 : 0;
  }

  setSize(width, height) {
    setStyle({
      width,
      height
    }, this.wrap);
  }

  switchVideo(id) {
    this.media.loadVideoById({ videoId: id });
  }

  createHtml() {
    let poster = '';

    if (this.options.poster !== '') {
      poster = templateEngine.render(this.options.templates.poster.call(this), {
        classes: this.classes
      });
    }

    const html$$1 = templateEngine.render(this.options.template.call(this), {
      classes: this.classes,
      poster
    });
    return html$$1;
  }

  bind() {
    this.media.addEventListener('onStateChange', event => {
      if (event.data === 1) {
        this.instance.trigger(events.PLAY);
      } else if (event.data === 2) {
        this.instance.trigger(events.PAUSE);
      } else if (event.data === 0) {
        this.instance.trigger(events.PLAYEND);
        if (this.options.loop === true) {
          this.play();
        }
      }
    });
    this.media.addEventListener('onError', () => {
      this.instance.trigger(events.PLAYERR);
    });
  }

  currentTime() {
    return this.media.getCurrentTime();
  }

  duration() {
    return this.media.getDuration();
  }

  setCurrentTime(val) {
    this.media.seekTo(val, true);
  }

  volume(value) {
    this.media.setVolume(value);
  }

  mute() {
    this.media.mute();
  }

  unMute() {
    this.media.unMute();
  }

  pause() {
    this.media.pauseVideo();
  }

  stop() {
    this.media.stopVideo();
    this.instance.trigger(events.STOP);
  }

  play() {
    this.media.playVideo();
  }

  destroy() {
    const element = query('iframe', this.wrap);
    if (element) {
      element.src = '//about:blank';
    }
    this.wrap.remove();
  }
};

var _dec, _dec2, _dec3, _dec4, _class;

const sources = {};

let Video = (_dec = styleable(classes), _dec2 = eventable(events), _dec3 = stateable(), _dec4 = register(namespace, {
  defaults: defaults,
  methods: methods
}, info), _dec(_class = _dec2(_class = _dec3(_class = _dec4(_class = class Video extends Component {
  constructor(element, options = {}) {
    super(namespace, element);

    this.options = deepMerge(defaults, options, this.getDataOptions());
    this.initClasses(classes);
    this.initStates();
    this.initialize();
  }

  initialize() {
    if (typeof sources[this.options.type] !== 'undefined') {
      this.player = new sources[this.options.type](this, this.element, this.options);
    }

    this.enter('initialized');
    this.trigger(events.READY);
  }

  load() {
    if (!this.is('loaded')) {
      this.player.load();
      this.enter('loaded');
    }
  }

  switchVideo(id) {
    this.player.switchVideo(id);
  }

  duration() {
    return this.player.duration();
  }

  currentTime() {
    return this.player.currentTime();
  }

  setCurrentTime(val) {
    this.player.setCurrentTime(val);
  }

  setSize(width, height) {
    this.player.setSize(width, height);
    this.options.width = width;
  }

  play() {
    this.player.play();
  }

  stop() {
    this.player.stop();
  }

  volume(val) {
    this.player.volume(val);
  }

  pause() {
    this.player.pause();
  }

  mute() {
    this.player.mute();
  }

  unMute() {
    this.player.unMute();
  }

  destroy() {
    if (this.is('initialized')) {
      this.leave('initialized');
    }
    if (this.is('loaded')) {
      this.leave('loaded');
      this.player.destroy();
    }
    this.trigger(events.DESTROY);
    super.destroy();
  }

  static registerSource(type, API) {
    sources[type] = API;
  }
}) || _class) || _class) || _class) || _class);


Video.registerSource('youtube', Youtube);
Video.registerSource('vimeo', Vimeo);
Video.registerSource('html5', Html5);

export default Video;
