(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@pluginjs/is'), require('@pluginjs/template'), require('@pluginjs/pluginjs'), require('@pluginjs/component')) :
  typeof define === 'function' && define.amd ? define(['exports', '@pluginjs/is', '@pluginjs/template', '@pluginjs/pluginjs', '@pluginjs/component'], factory) :
  (factory((global['@pluginjs/video'] = {}),global['@pluginjs/is'],global['@pluginjs/template'],global['@pluginjs/pluginjs'],global['@pluginjs/component']));
}(this, (function (exports,is,templateEngine,pluginjs,Component) { 'use strict';

  is = is && is.hasOwnProperty('default') ? is['default'] : is;
  templateEngine = templateEngine && templateEngine.hasOwnProperty('default') ? templateEngine['default'] : templateEngine;
  var pluginjs__default = 'default' in pluginjs ? pluginjs['default'] : pluginjs;
  Component = Component && Component.hasOwnProperty('default') ? Component['default'] : Component;

  var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
    return typeof obj;
  } : function (obj) {
    return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  };

  var classCallCheck = function (instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  };

  var createClass = function () {
    function defineProperties(target, props) {
      for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor) descriptor.writable = true;
        Object.defineProperty(target, descriptor.key, descriptor);
      }
    }

    return function (Constructor, protoProps, staticProps) {
      if (protoProps) defineProperties(Constructor.prototype, protoProps);
      if (staticProps) defineProperties(Constructor, staticProps);
      return Constructor;
    };
  }();

  var defineProperty = function (obj, key, value) {
    if (key in obj) {
      Object.defineProperty(obj, key, {
        value: value,
        enumerable: true,
        configurable: true,
        writable: true
      });
    } else {
      obj[key] = value;
    }

    return obj;
  };

  var get = function get(object, property, receiver) {
    if (object === null) object = Function.prototype;
    var desc = Object.getOwnPropertyDescriptor(object, property);

    if (desc === undefined) {
      var parent = Object.getPrototypeOf(object);

      if (parent === null) {
        return undefined;
      } else {
        return get(parent, property, receiver);
      }
    } else if ("value" in desc) {
      return desc.value;
    } else {
      var getter = desc.get;

      if (getter === undefined) {
        return undefined;
      }

      return getter.call(receiver);
    }
  };

  var inherits = function (subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
      throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }

    subClass.prototype = Object.create(superClass && superClass.prototype, {
      constructor: {
        value: subClass,
        enumerable: false,
        writable: true,
        configurable: true
      }
    });
    if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
  };

  var possibleConstructorReturn = function (self, call) {
    if (!self) {
      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
    }

    return call && (typeof call === "object" || typeof call === "function") ? call : self;
  };

  var slicedToArray = function () {
    function sliceIterator(arr, i) {
      var _arr = [];
      var _n = true;
      var _d = false;
      var _e = undefined;

      try {
        for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
          _arr.push(_s.value);

          if (i && _arr.length === i) break;
        }
      } catch (err) {
        _d = true;
        _e = err;
      } finally {
        try {
          if (!_n && _i["return"]) _i["return"]();
        } finally {
          if (_d) throw _e;
        }
      }

      return _arr;
    }

    return function (arr, i) {
      if (Array.isArray(arr)) {
        return arr;
      } else if (Symbol.iterator in Object(arr)) {
        return sliceIterator(arr, i);
      } else {
        throw new TypeError("Invalid attempt to destructure non-iterable instance");
      }
    };
  }();

  var toConsumableArray = function (arr) {
    if (Array.isArray(arr)) {
      for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];

      return arr2;
    } else {
      return Array.from(arr);
    }
  };

  var _extends$1 = 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 === 'undefined' ? 'undefined' : _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(function (key) {
        return [key, deepMergeTwo(x[key], y[key])];
      }));
    }

    if (isPlainObject(y) && typeof x === 'function') {
      return Object.assign(function () {
        for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
          args[_key2] = arguments[_key2];
        }

        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 () {
        for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
          args[_key3] = arguments[_key3];
        }

        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(function (index) {
        return deepMergeTwo(x[index], y[index]);
      });
    }

    if (typeof y === 'undefined') {
      return x;
    }
    return y;
  }
  function isObject(obj) {
    return Object(obj) === obj;
  }
  function deepMerge() {
    for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
      args[_key4] = arguments[_key4];
    }

    return args.filter(isObject).reduce(deepMergeTwo);
  }

  var curry = function curry(fn) {
    var args = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
    return function () {
      for (var _len5 = arguments.length, subArgs = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
        subArgs[_key5] = arguments[_key5];
      }

      var currylen = fn.currylen || fn.length;
      var collect = args.concat(subArgs);
      if (collect.length >= currylen) {
        return fn.apply(undefined, toConsumableArray(collect));
      }
      return curry(fn, collect);
    };
  };

  var compose = function compose() {
    for (var _len6 = arguments.length, fn = Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
      fn[_key6] = arguments[_key6];
    }

    var callback = function callback() {
      for (var _len7 = arguments.length, args = Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {
        args[_key7] = arguments[_key7];
      }

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

  function fromPairs$1(arr) {
    return arr.reduce(function (r, _ref10) {
      var _ref11 = slicedToArray(_ref10, 2),
          k = _ref11[0],
          v = _ref11[1];

      return _extends$1({}, r, defineProperty({}, k, v));
    }, {});
  }

  // last:: [a] -> a

  /**
   * setStyle({
   *  fontSize: '16px',
   *  display: 'flex'
   * }, element)
   */
  var setStyle = curry(function (style, el) {
    Object.entries(style).forEach(function (_ref) {
      var _ref2 = slicedToArray(_ref, 2),
          k = _ref2[0],
          v = _ref2[1];

      if (typeof v === 'number') {
        v = v.toString() + 'px';
      }
      el.style[k] = v;
    });
    return el;
  });

  var query = function query(selector) {
    var parent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document;
    return parent.querySelector(selector);
  };

  var html = curry(function (content, el) {
    el.innerHTML = content;
    return el;
  });

  var children = function children(el) {
    return Array.from(el.children);
  };

  var parent = function parent(el) {
    return el.parentNode;
  };
  // 解析 HTML/SVG/XML 字符串
  var parseHTML = function parseHTML() {
    for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    var htmlString = Array.isArray(args[0]) ? args[0].reduce(function (result, str, index) {
      return result + args[index] + str;
    }) : args[0];
    var childNodes = compose(children, html(htmlString))(document.createElement('div'));
    if (childNodes.length === 1) {
      return childNodes[0];
    }
    return childNodes;
  };

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

  var namespace = 'video';

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

  var classes = {
    NAMESPACE: 'pj-' + namespace,
    THEME: '{namespace}--{theme}',
    POSTER: '{namespace}-poster'
  };

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

  var defaults$1 = {
    template: function template() {
      return '<div class="{classes.NAMESPACE}">' + '{poster}' + '</div>';
    },

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

  var info = { version: '0.0.1' };

  var Html5 = function () {
    function Html5(video, element, options) {
      classCallCheck(this, Html5);

      this.element = element;
      this.options = options;
      this.instance = video;
      this.classes = video.classes;
    }

    createClass(Html5, [{
      key: 'load',
      value: function 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();
      }
    }, {
      key: 'setDefaultParameters',
      value: function setDefaultParameters() {
        if (is.array(this.options.url)) {
          for (var i = 0; i < this.options.url.length; i++) {
            var videoTypeArr = this.options.url[i].split('.');
            var videoType = videoTypeArr[videoTypeArr.length - 1];

            this.addSourceToVideo(this.options.url[i], videoType);
          }
        } else {
          var _videoTypeArr = this.options.url.split('.');
          var _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;
      }
    }, {
      key: 'createHtml',
      value: function createHtml() {
        var poster = '';

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

        var html$$1 = templateEngine.render(this.options.template.call(this), {
          classes: this.classes,
          poster: poster
        });
        return html$$1;
      }
    }, {
      key: 'addSourceToVideo',
      value: function addSourceToVideo(src, type) {
        var source = document.createElement('source');

        source.src = src;
        source.type = 'video/' + type;

        append(source, this.video);
      }
    }, {
      key: 'setSize',
      value: function setSize(width, height) {
        setStyle({
          width: width,
          height: height
        }, this.wrap);
      }
    }, {
      key: 'switchVideo',
      value: function switchVideo(id) {
        this.video.src = id;
      }
    }, {
      key: 'bind',
      value: function bind() {
        this.eventListener('play');
        this.eventListener('pause');
        this.eventListener('error');
        // this.eventListener('stalled')
      }
    }, {
      key: 'registerEvent',
      value: function 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);
      }
    }, {
      key: 'removeListener',
      value: function removeListener(eventName, element) {
        if (!this.listeners[eventName]) {
          console.log('not bind eventName:', eventName);
        }

        this.listeners[eventName].map(function (callback) {
          element.removeEventListener(eventName, callback);
        });
      }
    }, {
      key: 'unbind',
      value: function unbind() {
        this.removeListener('error', this.video);
        this.removeListener('play', this.video);
        this.removeListener('pause', this.video);
      }
    }, {
      key: 'eventListener',
      value: function eventListener(eventName) {
        var _this = this;

        var capitalEvent = eventName.toUpperCase();
        this.registerEvent(eventName, function () {
          _this.instance.trigger(events[capitalEvent]);
        }, this.video);
      }
    }, {
      key: 'currentTime',
      value: function currentTime() {
        return this.video.currentTime;
      }
    }, {
      key: 'duration',
      value: function duration() {
        return this.video.duration;
      }
    }, {
      key: 'setCurrentTime',
      value: function setCurrentTime(val) {
        this.video.currentTime = val;
      }
    }, {
      key: 'pause',
      value: function pause() {
        this.video.pause();
      }
    }, {
      key: 'play',
      value: function play() {
        this.video.play();
      }
    }, {
      key: 'mute',
      value: function mute() {
        this.video.muted = true;
      }
    }, {
      key: 'unMute',
      value: function unMute() {
        this.video.muted = false;
      }
    }, {
      key: 'stop',
      value: function stop() {
        this.video.currentTime = 0;
        this.video.pause();
        this.instance.trigger(events.STOP);
      }
    }, {
      key: 'volume',
      value: function volume(value) {
        this.video.volume = value / 100;
      }
    }, {
      key: 'destroy',
      value: function destroy() {
        this.unbind();
        var element = query('video', this.wrap);
        if (element) {
          element.src = '//about:blank';
        }
        this.wrap.remove();
      }
    }]);
    return Html5;
  }();

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

    return identity;
  };

  var tupleToStyleSelector = function tupleToStyleSelector(tuple, prefix) {
    if (typeof tuple === 'string') {
      return tuple;
    }
    return Object.entries(tuple).map(function (kv) {
      return '[' + prefix + kv.join('=') + ']';
    }).join('');
  };

  var dispatch = function dispatch(event) {
    var target = event.target,
        currentTarget = event.currentTarget;

    var eventStorage = EventStorage.getEventStorage(currentTarget);
    var eventName = event.type;

    var attrVerify$$1 = {
      self: function self(node) {
        return node === currentTarget;
      },
      class: function _class(node, value) {
        return node.matches('.' + value);
      },
      selector: function selector(node, value) {
        return node.matches(value);
      },
      id: function id(node, value) {
        return node.matches('#' + value);
      },
      tagName: function tagName(node, value) {
        return node.matches(value);
      },
      dom: function dom(node, value) {
        return node === value;
      },
      dataset: function dataset$$1(node, value) {
        return node.matches(tupleToStyleSelector(value, 'data-'));
      },
      attribute: function attribute(node, value) {
        return node.matches(tupleToStyleSelector(value));
      },
      func: function func(node, value) {
        return Boolean(value(node));
      }
    };

    var nodeTreeCheck = function nodeTreeCheck(node) {
      var result = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];

      if (!currentTarget.contains(node)) {
        return result;
      }

      var matchEventList = eventStorage.listeners[eventName].filter(function (_ref) {
        var identity = _ref.identity;
        var type = identity.type,
            value = identity.value;

        var 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(function (result, _ref2) {
      var handler = _ref2.handler;
      return result !== false && handler(event);
    }, true);
  };

  var EventStorage = function () {
    function EventStorage(element) {
      classCallCheck(this, EventStorage);

      this.element = element;
      this.listeners = {};
    }

    createClass(EventStorage, [{
      key: 'on',
      value: function on(_ref3) {
        var identity = _ref3.identity,
            handler = _ref3.handler,
            eventName = _ref3.eventName,
            namespace = _ref3.namespace;

        this.ensureHandler(handler);

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

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

        this.listeners[eventName].push({ identity: identity, handler: handler, namespace: namespace });
      }
    }, {
      key: 'once',
      value: function once(_ref4) {
        var _this = this;

        var identity = _ref4.identity,
            handler = _ref4.handler,
            eventName = _ref4.eventName,
            namespace = _ref4.namespace;

        this.ensureHandler(handler);

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

        var callback = function callback(event) {
          _this.removeListener(eventName, callback);

          return handler(event);
        };

        this.listeners[eventName].push({ identity: identity, handler: callback, namespace: namespace });
      }
    }, {
      key: 'off',
      value: function off(_eventName, handler) {
        if (typeof handler === 'undefined') {
          return this.removeAllListeners(_eventName);
        }
        return this.removeListener(_eventName, handler);
      }
    }, {
      key: 'trigger',
      value: function trigger(eventName, data) {
        var event = new CustomEvent(eventName, {
          detail: data
        });
        this.element.dispatchEvent(event);
      }
    }, {
      key: 'clear',
      value: function clear() {
        var _this2 = this;

        Object.entries(this.listeners).map(function (_ref5) {
          var _ref6 = slicedToArray(_ref5, 2),
              key = _ref6[0],
              value = _ref6[1];

          _this2.deleteEventListener(key);
        });

        this.listener = {};
      }
    }, {
      key: 'removeListener',
      value: function removeListener(_eventName, handler) {
        var _this3 = this;

        var _eventName$split = _eventName.split('.'),
            _eventName$split2 = slicedToArray(_eventName$split, 2),
            eventName = _eventName$split2[0],
            namespace = _eventName$split2[1];
        //   .example  || click  || click.example


        if (!eventName && namespace) {
          Object.entries(this.listeners).map(function (_ref7) {
            var _ref8 = slicedToArray(_ref7, 2),
                key = _ref8[0],
                value = _ref8[1];

            _this3.listeners[key] = _this3.listeners[key].filter(function (eventTuple) {
              return eventTuple.handler !== handler || eventTuple.namespace !== namespace;
            });

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

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

          if (this.listeners[eventName].length === 0) {
            this.deleteEventListener(eventName);
          }
        }
      }
    }, {
      key: 'removeAllListeners',
      value: function removeAllListeners(_eventName) {
        var _this4 = this;

        var _eventName$split3 = _eventName.split('.'),
            _eventName$split4 = slicedToArray(_eventName$split3, 2),
            eventName = _eventName$split4[0],
            namespace = _eventName$split4[1];
        //   .example  || click  || click.example


        if (!eventName && namespace) {
          Object.entries(this.listeners).map(function (_ref9) {
            var _ref10 = slicedToArray(_ref9, 2),
                key = _ref10[0],
                value = _ref10[1];

            _this4.listeners[key] = _this4.listeners[key].filter(function (eventTuple) {
              return eventTuple.namespace !== namespace;
            });

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

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

        return this;
      }
    }, {
      key: 'createEventListener',
      value: function createEventListener(eventName) {
        this.listeners[eventName] = [];
        this.element.addEventListener(eventName, dispatch, false);
      }
    }, {
      key: 'deleteEventListener',
      value: function deleteEventListener(eventName) {
        this.element.removeEventListener(eventName, dispatch);
        delete this.listeners[eventName];
      }
    }, {
      key: 'checkRepeats',
      value: function checkRepeats(eventName, handler) {
        return this.listeners[eventName].filter(function (value) {
          return value.handler === handler;
        }).length !== 0;
      }
    }, {
      key: 'hasListeners',
      value: function hasListeners(eventName) {
        if (!this.listeners[eventName] || Object.keys(this.listeners[eventName]).length === 0) {
          return false;
        }

        return true;
      }
    }, {
      key: 'ensureHandler',
      value: function ensureHandler(handler) {
        var type = typeof handler === 'undefined' ? 'undefined' : _typeof(handler);
        if (type === 'function') {
          return handler;
        }
        throw new TypeError('Listeners should be function or closure. Received type: ' + type);
      }
    }], [{
      key: 'of',
      value: function of(_ref11, element) {
        var _eventName = _ref11.type,
            identity = _ref11.identity,
            handler = _ref11.handler;

        if (!element.__eventStorage) {
          element.__eventStorage = new this(element);
        }

        var _eventName$split5 = _eventName.split('.'),
            _eventName$split6 = slicedToArray(_eventName$split5, 2),
            eventName = _eventName$split6[0],
            namespace = _eventName$split6[1];

        var eventStorage = this.getEventStorage(element);

        eventStorage.on({
          identity: outputIdentity(identity),
          handler: handler,
          eventName: eventName,
          namespace: namespace
        });
      }
    }, {
      key: 'once',
      value: function once(_ref12, element) {
        var _eventName = _ref12.type,
            identity = _ref12.identity,
            handler = _ref12.handler;

        if (!element.__eventStorage) {
          element.__eventStorage = new this(element);
        }

        var _eventName$split7 = _eventName.split('.'),
            _eventName$split8 = slicedToArray(_eventName$split7, 2),
            eventName = _eventName$split8[0],
            namespace = _eventName$split8[1];

        var eventStorage = this.getEventStorage(element);

        eventStorage.once({
          identity: outputIdentity(identity),
          handler: handler,
          eventName: eventName,
          namespace: namespace
        });
      }
    }, {
      key: 'delete',
      value: function _delete(options, element) {
        var eventStorage = this.getEventStorage(element);
        if (!eventStorage) {
          return;
        }

        var _options$type = options.type,
            _eventName = _options$type === undefined ? options : _options$type,
            handler = options.handler;

        eventStorage.off(_eventName, handler);
      }
    }, {
      key: 'getEventStorage',
      value: function getEventStorage(element) {
        return element.__eventStorage;
      }
    }]);
    return EventStorage;
  }();

  var trigger = curry(function (options, el) {
    var _options$type = options.type,
        type = _options$type === undefined ? options : _options$type,
        data = options.data;

    var eventName = type;

    var 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)
   */

  var bindEvent = curry(function (options, element) {
    EventStorage.of(options, element);
    return element;
  });

  window.AsVimeoAPIReady = false;

  var Vimeo = function () {
    function Vimeo(instance, element, options) {
      classCallCheck(this, Vimeo);

      this.element = element;
      this.options = options;
      this.instance = instance;
      this.classes = instance.classes;
    }

    createClass(Vimeo, [{
      key: 'load',
      value: function load() {
        var _this = this;

        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: function handler() {
              _this.init();
              _this.instance.trigger(events.LOAD);
            }
          }, this.element);
        }
      }
    }, {
      key: 'init',
      value: function init() {
        var 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();
      }
    }, {
      key: 'getId',
      value: function getId() {
        if (this.options.id) {
          return this.options.id;
        } else if (this.options.url) {
          return this.options.url.split('/')[3].split('?')[0];
        }
        return undefined;
      }
    }, {
      key: 'createHtml',
      value: function createHtml() {
        var poster = '';

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

        var html$$1 = templateEngine.render(this.options.template.call(this), {
          classes: this.classes,
          poster: poster
        });
        return html$$1;
      }
    }, {
      key: 'loadApi',
      value: function loadApi() {
        var _this2 = this;

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

        var count = 1;
        var vimeoApiReady = setInterval(function () {
          if (count > 50) {
            clearInterval(vimeoApiReady);
            console.log('loadApi error');
            _this2.instance.destroy();
          }
          count++;
          if (typeof window.Vimeo === 'undefined') {
            return;
          }
          window.AsVimeoAPIReady = true;
          trigger('AsVideoVimeoAPIReady', _this2.element);
          clearInterval(vimeoApiReady);
        }, 350);
      }
    }, {
      key: 'bind',
      value: function bind() {
        var _this3 = this;

        this.media.on('play', function () {
          _this3.instance.trigger(events.PLAY);
        });
        this.media.on('pause', function () {
          _this3.instance.trigger(events.PAUSE);
        });
        this.media.on('loaded', function () {
          _this3.instance.trigger(events.LOADED);
          if (_this3.options.poster) {
            _this3.poster.style.display = 'none';
          }
        });
      }
    }, {
      key: 'setSize',
      value: function setSize(width, height) {
        setStyle({
          width: width,
          height: height
        }, this.wrap);
      }
    }, {
      key: 'switchVideo',
      value: function switchVideo(id) {
        this.media.loadVideo(id);
      }
    }, {
      key: '_currentTime',
      value: function _currentTime() {
        var _this4 = this;

        this.media.getCurrentTime().then(function (seconds) {
          _this4.options.currentTime = seconds;
        });
      }
    }, {
      key: 'currentTime',
      value: function currentTime() {
        this._currentTime();
        return this.options.currentTime;
      }
    }, {
      key: '_duration',
      value: function _duration() {
        var _this5 = this;

        return this.media.getDuration().then(function (duration) {
          _this5.options.duration = duration;
        });
      }
    }, {
      key: 'duration',
      value: function duration() {
        this._duration();
        return this.options.duration;
      }
    }, {
      key: 'setCurrentTime',
      value: function setCurrentTime(val) {
        this.media.setCurrentTime(val);
      }
    }, {
      key: 'stop',
      value: function stop() {
        this.media.setCurrentTime(0);
        this.media.pause();
        this.instance.trigger(events.STOP);
      }
    }, {
      key: 'mute',
      value: function mute() {
        this.volume(0);
      }
    }, {
      key: 'unMute',
      value: function unMute() {
        this.volume(50);
      }
    }, {
      key: 'pause',
      value: function pause() {
        this.media.pause();
        this.instance.trigger('pause');
      }
    }, {
      key: 'volume',
      value: function volume(value) {
        this.media.setVolume(value / 100);
      }
    }, {
      key: 'play',
      value: function play() {
        this.media.play();
      }
    }, {
      key: 'destroy',
      value: function destroy() {
        var element = query('iframe', this.wrap);
        if (element) {
          element.src = '//about:blank';
        }
        this.wrap.remove();
      }
    }]);
    return Vimeo;
  }();

  window.AsYTAPIReady = false;

  var Youtube = function () {
    function Youtube(instance, element, options) {
      classCallCheck(this, Youtube);

      this.element = element;
      this.options = options;
      this.instance = instance;
      this.classes = instance.classes;
    }

    createClass(Youtube, [{
      key: 'load',
      value: function 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();
        }
      }
    }, {
      key: 'init',
      value: function init() {
        var _this = this;

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

        this.setdefault();

        var 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: function onReady() {
              _this.instance.trigger(events.LOADED);
              if (_this.options.poster) {
                _this.poster.style.display = 'none';
              }
            }
          }
        });
        this.bind();
      }
    }, {
      key: 'getId',
      value: function 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;
      }
    }, {
      key: 'loadApi',
      value: function loadApi() {
        var _this2 = this;

        window.onYouTubeIframeAPIReady = function () {
          _this2.init();
          window.AsYTAPIReady = true;
          _this2.instance.trigger(events.LOAD);
        };

        var tag = document.createElement('script');
        tag.src = 'https://www.youtube.com/iframe_api';
        var firstScriptTag = document.getElementsByTagName('script')[0];
        firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
      }
    }, {
      key: 'setdefault',
      value: function setdefault() {
        this.options.autoplay = this.options.autoplay ? 1 : 0;
        this.options.controls = this.options.controls ? 1 : 0;
      }
    }, {
      key: 'setSize',
      value: function setSize(width, height) {
        setStyle({
          width: width,
          height: height
        }, this.wrap);
      }
    }, {
      key: 'switchVideo',
      value: function switchVideo(id) {
        this.media.loadVideoById({ videoId: id });
      }
    }, {
      key: 'createHtml',
      value: function createHtml() {
        var poster = '';

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

        var html$$1 = templateEngine.render(this.options.template.call(this), {
          classes: this.classes,
          poster: poster
        });
        return html$$1;
      }
    }, {
      key: 'bind',
      value: function bind() {
        var _this3 = this;

        this.media.addEventListener('onStateChange', function (event) {
          if (event.data === 1) {
            _this3.instance.trigger(events.PLAY);
          } else if (event.data === 2) {
            _this3.instance.trigger(events.PAUSE);
          } else if (event.data === 0) {
            _this3.instance.trigger(events.PLAYEND);
            if (_this3.options.loop === true) {
              _this3.play();
            }
          }
        });
        this.media.addEventListener('onError', function () {
          _this3.instance.trigger(events.PLAYERR);
        });
      }
    }, {
      key: 'currentTime',
      value: function currentTime() {
        return this.media.getCurrentTime();
      }
    }, {
      key: 'duration',
      value: function duration() {
        return this.media.getDuration();
      }
    }, {
      key: 'setCurrentTime',
      value: function setCurrentTime(val) {
        this.media.seekTo(val, true);
      }
    }, {
      key: 'volume',
      value: function volume(value) {
        this.media.setVolume(value);
      }
    }, {
      key: 'mute',
      value: function mute() {
        this.media.mute();
      }
    }, {
      key: 'unMute',
      value: function unMute() {
        this.media.unMute();
      }
    }, {
      key: 'pause',
      value: function pause() {
        this.media.pauseVideo();
      }
    }, {
      key: 'stop',
      value: function stop() {
        this.media.stopVideo();
        this.instance.trigger(events.STOP);
      }
    }, {
      key: 'play',
      value: function play() {
        this.media.playVideo();
      }
    }, {
      key: 'destroy',
      value: function destroy() {
        var element = query('iframe', this.wrap);
        if (element) {
          element.src = '//about:blank';
        }
        this.wrap.remove();
      }
    }]);
    return Youtube;
  }();

  var _dec, _dec2, _dec3, _dec4, _class;

  var sources = {};

  var Video = (_dec = pluginjs.styleable(classes), _dec2 = pluginjs.eventable(events), _dec3 = pluginjs.stateable(), _dec4 = pluginjs.register(namespace, {
    defaults: defaults$1,
    methods: methods
  }, info), _dec(_class = _dec2(_class = _dec3(_class = _dec4(_class = function (_Component) {
    inherits(Video, _Component);

    function Video(element) {
      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      classCallCheck(this, Video);

      var _this = possibleConstructorReturn(this, (Video.__proto__ || Object.getPrototypeOf(Video)).call(this, namespace, element));

      _this.options = deepMerge(defaults$1, options, _this.getDataOptions());
      _this.initClasses(classes);
      _this.initStates();
      _this.initialize();
      return _this;
    }

    createClass(Video, [{
      key: 'initialize',
      value: function 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);
      }
    }, {
      key: 'load',
      value: function load() {
        if (!this.is('loaded')) {
          this.player.load();
          this.enter('loaded');
        }
      }
    }, {
      key: 'switchVideo',
      value: function switchVideo(id) {
        this.player.switchVideo(id);
      }
    }, {
      key: 'duration',
      value: function duration() {
        return this.player.duration();
      }
    }, {
      key: 'currentTime',
      value: function currentTime() {
        return this.player.currentTime();
      }
    }, {
      key: 'setCurrentTime',
      value: function setCurrentTime(val) {
        this.player.setCurrentTime(val);
      }
    }, {
      key: 'setSize',
      value: function setSize(width, height) {
        this.player.setSize(width, height);
        this.options.width = width;
      }
    }, {
      key: 'play',
      value: function play() {
        this.player.play();
      }
    }, {
      key: 'stop',
      value: function stop() {
        this.player.stop();
      }
    }, {
      key: 'volume',
      value: function volume(val) {
        this.player.volume(val);
      }
    }, {
      key: 'pause',
      value: function pause() {
        this.player.pause();
      }
    }, {
      key: 'mute',
      value: function mute() {
        this.player.mute();
      }
    }, {
      key: 'unMute',
      value: function unMute() {
        this.player.unMute();
      }
    }, {
      key: 'destroy',
      value: function destroy() {
        if (this.is('initialized')) {
          this.leave('initialized');
        }
        if (this.is('loaded')) {
          this.leave('loaded');
          this.player.destroy();
        }
        this.trigger(events.DESTROY);
        get(Video.prototype.__proto__ || Object.getPrototypeOf(Video.prototype), 'destroy', this).call(this);
      }
    }], [{
      key: 'registerSource',
      value: function registerSource(type, API) {
        sources[type] = API;
      }
    }]);
    return Video;
  }(Component)) || _class) || _class) || _class) || _class);


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

  exports.default = Video;

  Object.defineProperty(exports, '__esModule', { value: true });

})));
