import React from 'react';
import { a as commonjsGlobal } from './_commonjsHelpers-0c4b6f40.js';

var slice = Array.prototype.slice;

var domWalk = iterativelyWalk;

function iterativelyWalk(nodes, cb) {
    if (!('length' in nodes)) {
        nodes = [nodes];
    }
    
    nodes = slice.call(nodes);

    while(nodes.length) {
        var node = nodes.shift(),
            ret = cb(node);

        if (ret) {
            return ret
        }

        if (node.childNodes && node.childNodes.length) {
            nodes = slice.call(node.childNodes).concat(nodes);
        }
    }
}

var domComment = Comment;

function Comment(data, owner) {
    if (!(this instanceof Comment)) {
        return new Comment(data, owner)
    }

    this.data = data;
    this.nodeValue = data;
    this.length = data.length;
    this.ownerDocument = owner || null;
}

Comment.prototype.nodeType = 8;
Comment.prototype.nodeName = "#comment";

Comment.prototype.toString = function _Comment_toString() {
    return "[object Comment]"
};

var domText = DOMText;

function DOMText(value, owner) {
    if (!(this instanceof DOMText)) {
        return new DOMText(value)
    }

    this.data = value || "";
    this.length = this.data.length;
    this.ownerDocument = owner || null;
}

DOMText.prototype.type = "DOMTextNode";
DOMText.prototype.nodeType = 3;
DOMText.prototype.nodeName = "#text";

DOMText.prototype.toString = function _Text_toString() {
    return this.data
};

DOMText.prototype.replaceData = function replaceData(index, length, value) {
    var current = this.data;
    var left = current.substring(0, index);
    var right = current.substring(index + length, current.length);
    this.data = left + value + right;
    this.length = this.data.length;
};

var dispatchEvent_1 = dispatchEvent;

function dispatchEvent(ev) {
    var elem = this;
    var type = ev.type;

    if (!ev.target) {
        ev.target = elem;
    }

    if (!elem.listeners) {
        elem.listeners = {};
    }

    var listeners = elem.listeners[type];

    if (listeners) {
        return listeners.forEach(function (listener) {
            ev.currentTarget = elem;
            if (typeof listener === 'function') {
                listener(ev);
            } else {
                listener.handleEvent(ev);
            }
        })
    }

    if (elem.parentNode) {
        elem.parentNode.dispatchEvent(ev);
    }
}

var addEventListener_1 = addEventListener;

function addEventListener(type, listener) {
    var elem = this;

    if (!elem.listeners) {
        elem.listeners = {};
    }

    if (!elem.listeners[type]) {
        elem.listeners[type] = [];
    }

    if (elem.listeners[type].indexOf(listener) === -1) {
        elem.listeners[type].push(listener);
    }
}

var removeEventListener_1 = removeEventListener;

function removeEventListener(type, listener) {
    var elem = this;

    if (!elem.listeners) {
        return
    }

    if (!elem.listeners[type]) {
        return
    }

    var list = elem.listeners[type];
    var index = list.indexOf(listener);
    if (index !== -1) {
        list.splice(index, 1);
    }
}

var serialize = serializeNode;

var voidElements = ["area","base","br","col","embed","hr","img","input","keygen","link","menuitem","meta","param","source","track","wbr"];

function serializeNode(node) {
    switch (node.nodeType) {
        case 3:
            return escapeText(node.data)
        case 8:
            return "<!--" + node.data + "-->"
        default:
            return serializeElement(node)
    }
}

function serializeElement(elem) {
    var strings = [];

    var tagname = elem.tagName;

    if (elem.namespaceURI === "http://www.w3.org/1999/xhtml") {
        tagname = tagname.toLowerCase();
    }

    strings.push("<" + tagname + properties(elem) + datasetify(elem));

    if (voidElements.indexOf(tagname) > -1) {
        strings.push(" />");
    } else {
        strings.push(">");

        if (elem.childNodes.length) {
            strings.push.apply(strings, elem.childNodes.map(serializeNode));
        } else if (elem.textContent || elem.innerText) {
            strings.push(escapeText(elem.textContent || elem.innerText));
        } else if (elem.innerHTML) {
            strings.push(elem.innerHTML);
        }

        strings.push("</" + tagname + ">");
    }

    return strings.join("")
}

function isProperty(elem, key) {
    var type = typeof elem[key];

    if (key === "style" && Object.keys(elem.style).length > 0) {
      return true
    }

    return elem.hasOwnProperty(key) &&
        (type === "string" || type === "boolean" || type === "number") &&
        key !== "nodeName" && key !== "className" && key !== "tagName" &&
        key !== "textContent" && key !== "innerText" && key !== "namespaceURI" &&  key !== "innerHTML"
}

function stylify(styles) {
    if (typeof styles === 'string') return styles
    var attr = "";
    Object.keys(styles).forEach(function (key) {
        var value = styles[key];
        key = key.replace(/[A-Z]/g, function(c) {
            return "-" + c.toLowerCase();
        });
        attr += key + ":" + value + ";";
    });
    return attr
}

function datasetify(elem) {
    var ds = elem.dataset;
    var props = [];

    for (var key in ds) {
        props.push({ name: "data-" + key, value: ds[key] });
    }

    return props.length ? stringify(props) : ""
}

function stringify(list) {
    var attributes = [];
    list.forEach(function (tuple) {
        var name = tuple.name;
        var value = tuple.value;

        if (name === "style") {
            value = stylify(value);
        }

        attributes.push(name + "=" + "\"" + escapeAttributeValue(value) + "\"");
    });

    return attributes.length ? " " + attributes.join(" ") : ""
}

function properties(elem) {
    var props = [];
    for (var key in elem) {
        if (isProperty(elem, key)) {
            props.push({ name: key, value: elem[key] });
        }
    }

    for (var ns in elem._attributes) {
      for (var attribute in elem._attributes[ns]) {
        var prop = elem._attributes[ns][attribute];
        var name = (prop.prefix ? prop.prefix + ":" : "") + attribute;
        props.push({ name: name, value: prop.value });
      }
    }

    if (elem.className) {
        props.push({ name: "class", value: elem.className });
    }

    return props.length ? stringify(props) : ""
}

function escapeText(s) {
    var str = '';

    if (typeof(s) === 'string') { 
        str = s; 
    } else if (s) {
        str = s.toString();
    }

    return str
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
}

function escapeAttributeValue(str) {
    return escapeText(str).replace(/"/g, "&quot;")
}

var htmlns = "http://www.w3.org/1999/xhtml";

var domElement = DOMElement;

function DOMElement(tagName, owner, namespace) {
    if (!(this instanceof DOMElement)) {
        return new DOMElement(tagName)
    }

    var ns = namespace === undefined ? htmlns : (namespace || null);

    this.tagName = ns === htmlns ? String(tagName).toUpperCase() : tagName;
    this.nodeName = this.tagName;
    this.className = "";
    this.dataset = {};
    this.childNodes = [];
    this.parentNode = null;
    this.style = {};
    this.ownerDocument = owner || null;
    this.namespaceURI = ns;
    this._attributes = {};

    if (this.tagName === 'INPUT') {
      this.type = 'text';
    }
}

DOMElement.prototype.type = "DOMElement";
DOMElement.prototype.nodeType = 1;

DOMElement.prototype.appendChild = function _Element_appendChild(child) {
    if (child.parentNode) {
        child.parentNode.removeChild(child);
    }

    this.childNodes.push(child);
    child.parentNode = this;

    return child
};

DOMElement.prototype.replaceChild =
    function _Element_replaceChild(elem, needle) {
        // TODO: Throw NotFoundError if needle.parentNode !== this

        if (elem.parentNode) {
            elem.parentNode.removeChild(elem);
        }

        var index = this.childNodes.indexOf(needle);

        needle.parentNode = null;
        this.childNodes[index] = elem;
        elem.parentNode = this;

        return needle
    };

DOMElement.prototype.removeChild = function _Element_removeChild(elem) {
    // TODO: Throw NotFoundError if elem.parentNode !== this

    var index = this.childNodes.indexOf(elem);
    this.childNodes.splice(index, 1);

    elem.parentNode = null;
    return elem
};

DOMElement.prototype.insertBefore =
    function _Element_insertBefore(elem, needle) {
        // TODO: Throw NotFoundError if referenceElement is a dom node
        // and parentNode !== this

        if (elem.parentNode) {
            elem.parentNode.removeChild(elem);
        }

        var index = needle === null || needle === undefined ?
            -1 :
            this.childNodes.indexOf(needle);

        if (index > -1) {
            this.childNodes.splice(index, 0, elem);
        } else {
            this.childNodes.push(elem);
        }

        elem.parentNode = this;
        return elem
    };

DOMElement.prototype.setAttributeNS =
    function _Element_setAttributeNS(namespace, name, value) {
        var prefix = null;
        var localName = name;
        var colonPosition = name.indexOf(":");
        if (colonPosition > -1) {
            prefix = name.substr(0, colonPosition);
            localName = name.substr(colonPosition + 1);
        }
        if (this.tagName === 'INPUT' && name === 'type') {
          this.type = value;
        }
        else {
          var attributes = this._attributes[namespace] || (this._attributes[namespace] = {});
          attributes[localName] = {value: value, prefix: prefix};
        }
    };

DOMElement.prototype.getAttributeNS =
    function _Element_getAttributeNS(namespace, name) {
        var attributes = this._attributes[namespace];
        var value = attributes && attributes[name] && attributes[name].value;
        if (this.tagName === 'INPUT' && name === 'type') {
          return this.type;
        }
        if (typeof value !== "string") {
            return null
        }
        return value
    };

DOMElement.prototype.removeAttributeNS =
    function _Element_removeAttributeNS(namespace, name) {
        var attributes = this._attributes[namespace];
        if (attributes) {
            delete attributes[name];
        }
    };

DOMElement.prototype.hasAttributeNS =
    function _Element_hasAttributeNS(namespace, name) {
        var attributes = this._attributes[namespace];
        return !!attributes && name in attributes;
    };

DOMElement.prototype.setAttribute = function _Element_setAttribute(name, value) {
    return this.setAttributeNS(null, name, value)
};

DOMElement.prototype.getAttribute = function _Element_getAttribute(name) {
    return this.getAttributeNS(null, name)
};

DOMElement.prototype.removeAttribute = function _Element_removeAttribute(name) {
    return this.removeAttributeNS(null, name)
};

DOMElement.prototype.hasAttribute = function _Element_hasAttribute(name) {
    return this.hasAttributeNS(null, name)
};

DOMElement.prototype.removeEventListener = removeEventListener_1;
DOMElement.prototype.addEventListener = addEventListener_1;
DOMElement.prototype.dispatchEvent = dispatchEvent_1;

// Un-implemented
DOMElement.prototype.focus = function _Element_focus() {
    return void 0
};

DOMElement.prototype.toString = function _Element_toString() {
    return serialize(this)
};

DOMElement.prototype.getElementsByClassName = function _Element_getElementsByClassName(classNames) {
    var classes = classNames.split(" ");
    var elems = [];

    domWalk(this, function (node) {
        if (node.nodeType === 1) {
            var nodeClassName = node.className || "";
            var nodeClasses = nodeClassName.split(" ");

            if (classes.every(function (item) {
                return nodeClasses.indexOf(item) !== -1
            })) {
                elems.push(node);
            }
        }
    });

    return elems
};

DOMElement.prototype.getElementsByTagName = function _Element_getElementsByTagName(tagName) {
    tagName = tagName.toLowerCase();
    var elems = [];

    domWalk(this.childNodes, function (node) {
        if (node.nodeType === 1 && (tagName === '*' || node.tagName.toLowerCase() === tagName)) {
            elems.push(node);
        }
    });

    return elems
};

DOMElement.prototype.contains = function _Element_contains(element) {
    return domWalk(this, function (node) {
        return element === node
    }) || false
};

var domFragment = DocumentFragment;

function DocumentFragment(owner) {
    if (!(this instanceof DocumentFragment)) {
        return new DocumentFragment()
    }

    this.childNodes = [];
    this.parentNode = null;
    this.ownerDocument = owner || null;
}

DocumentFragment.prototype.type = "DocumentFragment";
DocumentFragment.prototype.nodeType = 11;
DocumentFragment.prototype.nodeName = "#document-fragment";

DocumentFragment.prototype.appendChild  = domElement.prototype.appendChild;
DocumentFragment.prototype.replaceChild = domElement.prototype.replaceChild;
DocumentFragment.prototype.removeChild  = domElement.prototype.removeChild;

DocumentFragment.prototype.toString =
    function _DocumentFragment_toString() {
        return this.childNodes.map(function (node) {
            return String(node)
        }).join("")
    };

var event = Event;

function Event(family) {}

Event.prototype.initEvent = function _Event_initEvent(type, bubbles, cancelable) {
    this.type = type;
    this.bubbles = bubbles;
    this.cancelable = cancelable;
};

Event.prototype.preventDefault = function _Event_preventDefault() {
    
};

var document$1 = Document;

function Document() {
    if (!(this instanceof Document)) {
        return new Document();
    }

    this.head = this.createElement("head");
    this.body = this.createElement("body");
    this.documentElement = this.createElement("html");
    this.documentElement.appendChild(this.head);
    this.documentElement.appendChild(this.body);
    this.childNodes = [this.documentElement];
    this.nodeType = 9;
}

var proto = Document.prototype;
proto.createTextNode = function createTextNode(value) {
    return new domText(value, this)
};

proto.createElementNS = function createElementNS(namespace, tagName) {
    var ns = namespace === null ? null : String(namespace);
    return new domElement(tagName, this, ns)
};

proto.createElement = function createElement(tagName) {
    return new domElement(tagName, this)
};

proto.createDocumentFragment = function createDocumentFragment() {
    return new domFragment(this)
};

proto.createEvent = function createEvent(family) {
    return new event(family)
};

proto.createComment = function createComment(data) {
    return new domComment(data, this)
};

proto.getElementById = function getElementById(id) {
    id = String(id);

    var result = domWalk(this.childNodes, function (node) {
        if (String(node.id) === id) {
            return node
        }
    });

    return result || null
};

proto.getElementsByClassName = domElement.prototype.getElementsByClassName;
proto.getElementsByTagName = domElement.prototype.getElementsByTagName;
proto.contains = domElement.prototype.contains;

proto.removeEventListener = removeEventListener_1;
proto.addEventListener = addEventListener_1;
proto.dispatchEvent = dispatchEvent_1;

var minDocument = new document$1();

var topLevel = typeof commonjsGlobal !== 'undefined' ? commonjsGlobal :
    typeof window !== 'undefined' ? window : {};


var doccy;

if (typeof document !== 'undefined') {
    doccy = document;
} else {
    doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];

    if (!doccy) {
        doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDocument;
    }
}

var document_1 = doccy;

var win;

if (typeof window !== "undefined") {
    win = window;
} else if (typeof commonjsGlobal !== "undefined") {
    win = commonjsGlobal;
} else if (typeof self !== "undefined"){
    win = self;
} else {
    win = {};
}

var window_1 = win;

/*! @name @brightcove/react-player-loader @version 1.4.1 @license Apache-2.0 */

function _extends() {
  _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;
  };

  return _extends.apply(this, arguments);
}

function _inheritsLoose(subClass, superClass) {
  subClass.prototype = Object.create(superClass.prototype);
  subClass.prototype.constructor = subClass;
  subClass.__proto__ = superClass;
}

function _assertThisInitialized(self) {
  if (self === void 0) {
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  }

  return self;
}

/*! @name @brightcove/player-loader @version 1.8.0 @license Apache-2.0 */

function _extends$1() {
  _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;
  };

  return _extends$1.apply(this, arguments);
}

var version = "1.8.0";

/*! @name @brightcove/player-url @version 1.2.0 @license Apache-2.0 */
var version$1 = "1.2.0";

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;
};

// The parameters that may include JSON.
var JSON_ALLOWED_PARAMS = ['catalogSearch', 'catalogSequence'];

// The parameters that may be set as query string parameters for iframes.
var IFRAME_ALLOWED_QUERY_PARAMS = ['adConfigId', 'applicationId', 'catalogSearch', 'catalogSequence', 'playlistId', 'playlistVideoId', 'videoId'];

/**
 * Gets the value of a parameter and encodes it as a string.
 *
 * For certain keys, JSON is allowed and will be encoded.
 *
 * @private
 * @param   {Object} params
 *          A parameters object. See README for details.
 *
 * @param   {string} key
 *          The key in the params object.
 *
 * @return  {string|undefined}
 *          The encoded value - or `undefined` if none.
 */
var getQueryParamValue = function getQueryParamValue(params, key) {

  if (!params || params[key] === undefined) {
    return;
  }

  // If it's not a string, such as with a catalog search or sequence, we
  // try to encode it as JSON.
  if (typeof params[key] !== 'string' && JSON_ALLOWED_PARAMS.indexOf(key) !== -1) {
    try {
      return encodeURIComponent(JSON.stringify(params[key]));
    } catch (x) {

      // If it's not a string and we can't encode as JSON, it's ignored entirely.
      return;
    }
  }

  return encodeURIComponent(String(params[key]).trim()) || undefined;
};

/**
 * In some cases, we need to add query string parameters to an iframe URL.
 *
 * @private
 * @param   {Object} params
 *          An object of query parameters.
 *
 * @return  {string}
 *          A query string starting with `?`. If no valid parameters are given,
 *          returns an empty string.
 */
var getQueryString = function getQueryString(params) {
  return Object.keys(params).filter(function (k) {
    return IFRAME_ALLOWED_QUERY_PARAMS.indexOf(k) !== -1;
  }).reduce(function (qs, k) {
    var value = getQueryParamValue(params, k);

    if (value !== undefined) {
      qs += qs ? '&' : '?';
      qs += encodeURIComponent(k) + '=' + value;
    }

    return qs;
  }, '');
};

/**
 * Generate a URL to a Brightcove Player.
 *
 * @param  {Object}  params
 *         A set of parameters describing the player URL to create.
 *
 * @param  {string}  params.accountId
 *         A Brightcove account ID.
 *
 * @param  {string}  [params.playerId="default"]
 *         A Brightcove player ID.
 *
 * @param  {string}  [params.embedId="default"]
 *         A Brightcove player embed ID.
 *
 * @param  {boolean} [params.iframe=false]
 *         Whether to return a URL for an HTML document to be embedded in
 *         an iframe.
 *
 * @param  {boolean} [params.minified=true]
 *         When the `iframe` argument is `false`, this can be used to control
 *         whether the minified or unminified JavaScript URL is returned.
 *
 * @param  {string} [params.base="https://players.brightcove.net"]
 *         A base CDN protocol and hostname. Mainly used for testing.
 *
 * @return {string}
 *         A URL to a Brightcove Player.
 */
var brightcovePlayerUrl = function brightcovePlayerUrl(_ref) {
  var accountId = _ref.accountId,
      _ref$base = _ref.base,
      base = _ref$base === undefined ? 'https://players.brightcove.net' : _ref$base,
      _ref$playerId = _ref.playerId,
      playerId = _ref$playerId === undefined ? 'default' : _ref$playerId,
      _ref$embedId = _ref.embedId,
      embedId = _ref$embedId === undefined ? 'default' : _ref$embedId,
      _ref$iframe = _ref.iframe,
      iframe = _ref$iframe === undefined ? false : _ref$iframe,
      _ref$minified = _ref.minified,
      minified = _ref$minified === undefined ? true : _ref$minified,
      _ref$queryParams = _ref.queryParams,
      queryParams = _ref$queryParams === undefined ? null : _ref$queryParams;

  var ext = '';

  if (iframe) {
    ext += 'html';
  } else {
    if (minified) {
      ext += 'min.';
    }
    ext += 'js';
  }

  if (base.charAt(base.length - 1) === '/') {
    base = base.substring(0, base.length - 1);
  }

  var qs = '';

  if (iframe && queryParams && (typeof queryParams === 'undefined' ? 'undefined' : _typeof(queryParams)) === 'object') {
    qs = getQueryString(queryParams);
  }

  accountId = encodeURIComponent(accountId);
  playerId = encodeURIComponent(playerId);
  embedId = encodeURIComponent(embedId);

  return base + '/' + accountId + '/' + playerId + '_' + embedId + '/index.' + ext + qs;
};

/**
 * The version of this module.
 *
 * @type {string}
 */
brightcovePlayerUrl.VERSION = version$1;

var DEFAULTS = {
  embedId: 'default',
  embedType: 'in-page',
  playerId: 'default',
  Promise: window_1.Promise,
  refNodeInsert: 'append'
};
var DEFAULT_ASPECT_RATIO = '16:9';
var DEFAULT_IFRAME_HORIZONTAL_PLAYLIST = false;
var DEFAULT_MAX_WIDTH = '100%';
var EMBED_TAG_NAME_VIDEO = 'video';
var EMBED_TAG_NAME_VIDEOJS = 'video-js';
var EMBED_TYPE_IN_PAGE = 'in-page';
var EMBED_TYPE_IFRAME = 'iframe';
var REF_NODE_INSERT_APPEND = 'append';
var REF_NODE_INSERT_PREPEND = 'prepend';
var REF_NODE_INSERT_BEFORE = 'before';
var REF_NODE_INSERT_AFTER = 'after';
var REF_NODE_INSERT_REPLACE = 'replace';
var JSON_ALLOWED_ATTRS = ['catalogSearch', 'catalogSequence'];

var BASE_URL = 'https://players.brightcove.net/';
/**
 * Gets the URL to a player on CDN.
 *
 * @private
 * @param  {Object} params
 *         A parameters object. See README for details.
 *
 * @return {string}
 *         A URL.
 */

var getUrl = function getUrl(params) {
  if (params.playerUrl) {
    return params.playerUrl;
  }

  var accountId = params.accountId,
      playerId = params.playerId,
      embedId = params.embedId,
      embedOptions = params.embedOptions;
  var iframe = params.embedType === EMBED_TYPE_IFRAME;
  return brightcovePlayerUrl({
    accountId: accountId,
    playerId: playerId,
    embedId: embedId,
    iframe: iframe,
    base: BASE_URL,
    // The unminified embed option is the exact reverse of the minified option
    // here.
    minified: embedOptions ? !embedOptions.unminified : true,
    // Pass the entire params object as query params. This is safe because
    // @brightcove/player-url only accepts a whitelist of parameters. Anything
    // else will be ignored.
    queryParams: params
  });
};
/**
 * Function used to get the base URL - primarily for testing.
 *
 * @private
 * @return {string}
 *         The current base URL.
 */


var getBaseUrl = function getBaseUrl() {
  return BASE_URL;
};
/**
 * Function used to set the base URL - primarily for testing.
 *
 * @private
 * @param {string} baseUrl
 *        A new base URL (instead of Brightcove CDN).
 */


var setBaseUrl = function setBaseUrl(baseUrl) {
  BASE_URL = baseUrl;
};

var urls = {
  getUrl: getUrl,
  getBaseUrl: getBaseUrl,
  setBaseUrl: setBaseUrl
};

/**
 * Is this value an element?
 *
 * @param  {Element} el
 *         A maybe element.
 *
 * @return {boolean}
 *         Whether or not the value is a element.
 */

var isEl = function isEl(el) {
  return Boolean(el && el.nodeType === 1);
};
/**
 * Is this value an element with a parent node?
 *
 * @param  {Element} el
 *         A maybe element.
 *
 * @return {boolean}
 *         Whether or not the value is a element with a parent node.
 */


var isElInDom = function isElInDom(el) {
  return Boolean(isEl(el) && el.parentNode);
};
/**
 * Creates an iframe embed code.
 *
 * @private
 * @param  {Object} params
 *         A parameters object. See README for details.
 *
 * @return {Element}
 *         The DOM element that will ultimately be passed to the `bc()` function.
 */


var createIframeEmbed = function createIframeEmbed(params) {
  var el = document_1.createElement('iframe');
  el.setAttribute('allow', 'autoplay;encrypted-media;fullscreen');
  el.setAttribute('allowfullscreen', 'allowfullscreen');
  el.src = urls.getUrl(params);
  return el;
};
/**
 * Creates an in-page embed code.
 *
 * @private
 * @param  {Object} params
 *         A parameters object. See README for details.
 *
 * @return {Element}
 *         The DOM element that will ultimately be passed to the `bc()` function.
 */


var createInPageEmbed = function createInPageEmbed(params) {
  var embedOptions = params.embedOptions; // We DO NOT include the data-account, data-player, or data-embed attributes
  // here because we will be manually initializing the player.

  var paramsToAttrs = {
    adConfigId: 'data-ad-config-id',
    applicationId: 'data-application-id',
    catalogSearch: 'data-catalog-search',
    catalogSequence: 'data-catalog-sequence',
    deliveryConfigId: 'data-delivery-config-id',
    playlistId: 'data-playlist-id',
    playlistVideoId: 'data-playlist-video-id',
    poster: 'poster',
    videoId: 'data-video-id'
  };
  var tagName = embedOptions && embedOptions.tagName || EMBED_TAG_NAME_VIDEOJS;
  var el = document_1.createElement(tagName);
  Object.keys(paramsToAttrs).filter(function (key) {
    return params[key];
  }).forEach(function (key) {
    var value; // If it's not a string, such as with a catalog search or sequence, we
    // try to encode it as JSON.

    if (typeof params[key] !== 'string' && JSON_ALLOWED_ATTRS.indexOf(key) !== -1) {
      try {
        value = JSON.stringify(params[key]); // If it fails, don't set anything.
      } catch (x) {
        return;
      }
    } else {
      value = String(params[key]).trim();
    }

    el.setAttribute(paramsToAttrs[key], value);
  });
  el.setAttribute('controls', 'controls');
  el.classList.add('video-js');
  return el;
};
/**
 * Wraps an element in responsive intrinsic ratio elements.
 *
 * @private
 * @param  {string} embedType
 *         The type of the embed.
 *
 * @param  {Object} embedOptions
 *         Embed options from the params.
 *
 * @param  {Element} el
 *         The DOM element.
 *
 * @return {Element}
 *         A new element (if needed).
 */


var wrapResponsive = function wrapResponsive(embedType, embedOptions, el) {
  if (!embedOptions.responsive) {
    return el;
  }

  el.style.position = 'absolute';
  el.style.top = '0px';
  el.style.right = '0px';
  el.style.bottom = '0px';
  el.style.left = '0px';
  el.style.width = '100%';
  el.style.height = '100%';

  var responsive = _extends$1({
    aspectRatio: DEFAULT_ASPECT_RATIO,
    iframeHorizontalPlaylist: DEFAULT_IFRAME_HORIZONTAL_PLAYLIST,
    maxWidth: DEFAULT_MAX_WIDTH
  }, embedOptions.responsive); // This value is validate at a higher level, so we can trust that it's in the
  // correct format.


  var aspectRatio = responsive.aspectRatio.split(':').map(Number);
  var inner = document_1.createElement('div');
  var paddingTop = aspectRatio[1] / aspectRatio[0] * 100; // For iframes with a horizontal playlist, the playlist takes up 20% of the
  // vertical space (if shown); so, adjust the vertical size of the embed to
  // avoid black bars.

  if (embedType === EMBED_TYPE_IFRAME && responsive.iframeHorizontalPlaylist) {
    paddingTop *= 1.25;
  }

  inner.style.paddingTop = paddingTop + '%';
  inner.appendChild(el);
  var outer = document_1.createElement('div');
  outer.style.position = 'relative';
  outer.style.display = 'block';
  outer.style.maxWidth = responsive.maxWidth;
  outer.appendChild(inner);
  return outer;
};
/**
 * Wraps an element in a Picture-in-Picture plugin container.
 *
 * @private
 * @param  {Object} embedOptions
 *         Embed options from the params.
 *
 * @param  {Element} el
 *         The DOM element.
 *
 * @return {Element}
 *         A new element (if needed).
 */


var wrapPip = function wrapPip(embedOptions, el) {
  if (!embedOptions.pip) {
    return el;
  }

  var pip = document_1.createElement('div');
  pip.classList.add('vjs-pip-container');
  pip.appendChild(el);
  return pip;
};
/**
 * Wraps a bare embed element with necessary parent elements, depending on
 * embed options given in params.
 *
 * @private
 * @param  {string} embedType
 *         The type of the embed.
 *
 * @param  {Object} embedOptions
 *         Embed options from the params.
 *
 * @param  {Element} embed
 *         The embed DOM element.
 *
 * @return {Element}
 *         A new element (if needed) or the embed itself.
 */


var wrapEmbed = function wrapEmbed(embedType, embedOptions, embed) {
  if (!embedOptions) {
    return embed;
  }

  return wrapPip(embedOptions, wrapResponsive(embedType, embedOptions, embed));
};
/**
 * Inserts a previously-created embed element into the page based on params.
 *
 * @private
 * @param  {Object} params
 *         A parameters object. See README for details.
 *
 * @param  {Element} embed
 *         The embed DOM element.
 *
 * @return {Element}
 *         The embed DOM element.
 */


var insertEmbed = function insertEmbed(params, embed) {
  var refNode = params.refNode,
      refNodeInsert = params.refNodeInsert;
  var refNodeParent = refNode.parentNode; // Wrap the embed, if needed, in container elements to support various
  // plugins.

  var wrapped = wrapEmbed(params.embedType, params.embedOptions, embed); // Decide where to insert the wrapped embed.

  if (refNodeInsert === REF_NODE_INSERT_BEFORE) {
    refNodeParent.insertBefore(wrapped, refNode);
  } else if (refNodeInsert === REF_NODE_INSERT_AFTER) {
    refNodeParent.insertBefore(wrapped, refNode.nextElementSibling || null);
  } else if (refNodeInsert === REF_NODE_INSERT_REPLACE) {
    refNodeParent.replaceChild(wrapped, refNode);
  } else if (refNodeInsert === REF_NODE_INSERT_PREPEND) {
    refNode.insertBefore(wrapped, refNode.firstChild || null); // Append is the default.
  } else {
    refNode.appendChild(wrapped);
  } // If the playlist embed option is provided, we need to add a playlist element
  // immediately after the embed. This has to happen after the embed is inserted
  // into the DOM (above).


  if (params.embedOptions && params.embedOptions.playlist) {
    var playlistTagName = params.embedOptions.playlist.legacy ? 'ul' : 'div';
    var playlist = document_1.createElement(playlistTagName);
    playlist.classList.add('vjs-playlist');
    embed.parentNode.insertBefore(playlist, embed.nextElementSibling || null);
  } // Clean up internal reference to the refNode to avoid potential memory
  // leaks in case the params get persisted somewhere. We won't need it beyond
  // this point.


  params.refNode = null; // Return the original embed element that can be passed to `bc()`.

  return embed;
};
/**
 * Handles `onEmbedCreated` callback invocation.
 *
 * @private
 * @param  {Object} params
 *         A parameters object. See README for details.
 *
 * @param  {Element} embed
 *         The embed DOM element.
 *
 * @return {Element}
 *         A possibly-new DOM element.
 */


var onEmbedCreated = function onEmbedCreated(params, embed) {
  if (typeof params.onEmbedCreated !== 'function') {
    return embed;
  }

  var result = params.onEmbedCreated(embed);

  if (isEl(result)) {
    return result;
  }

  return embed;
};
/**
 * Creates an embed code of the appropriate type, runs any customizations
 * necessary, and inserts it into the DOM.
 *
 * @param  {Object} params
 *         A parameters object. See README for details.
 *
 * @return {Element}
 *         The DOM element that will ultimately be passed to the `bc()`
 *         function. Even when customized or wrapped, the return value will be
 *         the target element.
 */


var createEmbed = function createEmbed(params) {
  var embed = params.embedType === EMBED_TYPE_IFRAME ? createIframeEmbed(params) : createInPageEmbed(params);
  return insertEmbed(params, onEmbedCreated(params, embed));
};

//
// The keys follow the format "accountId_playerId_embedId" where accountId is
// optional and defaults to "*". This happens when we detect pre-existing
// player globals.

var actualCache = new window_1.Map();
/**
 * Get the cache key given some properties.
 *
 * @private
 * @param  {Object} props
 *         Properties describing the player record to cache.
 *
 * @param  {string} props.playerId
 *         A player ID.
 *
 * @param  {string} props.embedId
 *         An embed ID.
 *
 * @param  {string} [props.accountId="*"]
 *         An optional account ID. This is optional because when we search for
 *         pre-existing players to avoid downloads, we will not necessarily
 *         know the account ID.
 *
 * @return {string}
 *         A key to be used in the script cache.
 */

var key = function key(_ref) {
  var accountId = _ref.accountId,
      playerId = _ref.playerId,
      embedId = _ref.embedId;
  return (accountId || '*') + "_" + playerId + "_" + embedId;
};
/**
 * Add an entry to the script cache.
 *
 * @private
 * @param  {Object} props
 *         Properties describing the player record to cache.
 *
 * @param  {string} props.playerId
 *         A player ID.
 *
 * @param  {string} props.embedId
 *         An embed ID.
 *
 * @param  {string} [props.accountId="*"]
 *         An optional account ID. This is optional because when we search for
 *         pre-existing players to avoid downloads, we will not necessarily
 *         know the account ID. If not given, we assume that no script was
 *         downloaded for this player.
 */


var store = function store(props) {
  actualCache.set(key(props), props.accountId ? urls.getUrl(props) : '');
};
/**
 * Checks if the script cache has an entry.
 *
 * @private
 * @param  {Object} props
 *         Properties describing the player record to cache.
 *
 * @param  {string} props.playerId
 *         A player ID.
 *
 * @param  {string} props.embedId
 *         An embed ID.
 *
 * @param  {string} [props.accountId="*"]
 *         An optional account ID. This is optional because when we search for
 *         pre-existing players to avoid downloads, we will not necessarily
 *         know the account ID.
 *
 * @return {boolean}
 *         Will be `true` if there is a matching cache entry.
 */


var has = function has(props) {
  return actualCache.has(key(props));
};
/**
 * Gets a cache entry.
 *
 * @private
 * @param  {Object} props
 *         Properties describing the player record to cache.
 *
 * @param  {string} props.playerId
 *         A player ID.
 *
 * @param  {string} props.embedId
 *         An embed ID.
 *
 * @param  {string} [props.accountId="*"]
 *         An optional account ID. This is optional because when we search for
 *         pre-existing players to avoid downloads, we will not necessarily
 *         know the account ID.
 *
 * @return {string}
 *         A cache entry - a URL or empty string.
 *
 */


var get = function get(props) {
  return actualCache.get(key(props));
};
/**
 * Clears the cache.
 */


var clear = function clear() {
  actualCache.clear();
};
/**
 * Iterates over the cache.
 *
 * @param  {Function} fn
 *         A callback function that will be called with a value and a key
 *         for each item in the cache.
 */


var forEach = function forEach(fn) {
  actualCache.forEach(fn);
};

var playerScriptCache = {
  clear: clear,
  forEach: forEach,
  get: get,
  has: has,
  key: key,
  store: store
};

var REGEX_PLAYER_EMBED = /^([A-Za-z0-9]+)_([A-Za-z0-9]+)$/;
/**
 * Gets an array of current per-player/per-embed `bc` globals that are
 * attached to the `bc` global (e.g. `bc.abc123xyz_default`).
 *
 * If `bc` is not defined, returns an empty array.
 *
 * @private
 * @return {string[]}
 *         An array of keys.
 */

var getBcGlobalKeys = function getBcGlobalKeys() {
  return window_1.bc ? Object.keys(window_1.bc).filter(function (k) {
    return REGEX_PLAYER_EMBED.test(k);
  }) : [];
};
/**
 * Gets known global object keys that Brightcove Players may create.
 *
 * @private
 * @return {string[]}
 *         An array of global variables that were added during testing.
 */


var getGlobalKeys = function getGlobalKeys() {
  return Object.keys(window_1).filter(function (k) {
    return /^videojs/i.test(k) || /^(bc)$/.test(k);
  });
};
/**
 * Dispose all players from a copy of Video.js.
 *
 * @param  {Function} videojs
 *         A copy of Video.js.
 */


var disposeAll = function disposeAll(videojs) {
  if (!videojs) {
    return;
  }

  Object.keys(videojs.players).forEach(function (k) {
    var p = videojs.players[k];

    if (p) {
      p.dispose();
    }
  });
};
/**
 * Resets environment state.
 *
 * This will dispose ALL Video.js players on the page and remove ALL `bc` and
 * `videojs` globals it finds.
 */


var reset = function reset() {
  // Remove all script elements from the DOM.
  playerScriptCache.forEach(function (value, key) {
    // If no script URL is associated, skip it.
    if (!value) {
      return;
    } // Find all script elements and remove them.


    Array.prototype.slice.call(document_1.querySelectorAll("script[src=\"" + value + "\"]")).forEach(function (el) {
      return el.parentNode.removeChild(el);
    });
  }); // Clear the internal cache that have been downloaded.

  playerScriptCache.clear(); // Dispose any remaining players from the `videojs` global.

  disposeAll(window_1.videojs); // There may be other `videojs` instances lurking in the bowels of the
  // `bc` global. This should eliminate any of those.

  getBcGlobalKeys().forEach(function (k) {
    return disposeAll(window_1.bc[k].videojs);
  }); // Delete any global object keys that were created.

  getGlobalKeys().forEach(function (k) {
    delete window_1[k];
  });
};
/**
 * At runtime, populate the cache with pre-detected players. This allows
 * people who have bundled their player or included a script tag before this
 * runs to not have to re-download players.
 */


var detectPlayers = function detectPlayers() {
  getBcGlobalKeys().forEach(function (k) {
    var matches = k.match(REGEX_PLAYER_EMBED);
    var props = {
      playerId: matches[1],
      embedId: matches[2]
    };

    if (!playerScriptCache.has(props)) {
      playerScriptCache.store(props);
    }
  });
};

var env = {
  detectPlayers: detectPlayers,
  reset: reset
};

env.detectPlayers();
/**
 * Is this value a function?
 *
 * @private
 * @param  {Function} fn
 *         A maybe function.
 *
 * @return {boolean}
 *         Whether or not the value is a function.
 */

var isFn = function isFn(fn) {
  return typeof fn === 'function';
};
/**
 * Checks whether an embedType parameter is valid.
 *
 * @private
 * @param  {string} embedType
 *         The value to test.
 *
 * @return {boolean}
 *         Whether the value is valid.
 */


var isValidEmbedType = function isValidEmbedType(embedType) {
  return embedType === EMBED_TYPE_IN_PAGE || embedType === EMBED_TYPE_IFRAME;
};
/**
 * Checks whether an embedOptions.tagName parameter is valid.
 *
 * @private
 * @param  {string} tagName
 *         The value to test.
 *
 * @return {boolean}
 *         Whether the value is valid.
 */


var isValidTagName = function isValidTagName(tagName) {
  return tagName === EMBED_TAG_NAME_VIDEOJS || tagName === EMBED_TAG_NAME_VIDEO;
};
/**
 * Checks whether a refNodeInsert parameter is valid.
 *
 * @private
 * @param  {string} refNodeInsert
 *         The value to test.
 *
 * @return {boolean}
 *         Whether the value is valid.
 */


var isValidRootInsert = function isValidRootInsert(refNodeInsert) {
  return refNodeInsert === REF_NODE_INSERT_APPEND || refNodeInsert === REF_NODE_INSERT_PREPEND || refNodeInsert === REF_NODE_INSERT_BEFORE || refNodeInsert === REF_NODE_INSERT_AFTER || refNodeInsert === REF_NODE_INSERT_REPLACE;
};
/**
 * Checks parameters and throws an error on validation problems.
 *
 * @private
 * @param  {Object} params
 *         A parameters object. See README for details.
 *
 * @throws {Error} If accountId is missing.
 * @throws {Error} If refNode is missing or invalid.
 * @throws {Error} If embedType is missing or invalid.
 * @throws {Error} If attempting to use an iframe embed with options.
 * @throws {Error} If attempting to use embedOptions.responsiveIframe with a
 *                 non-iframe embed.
 * @throws {Error} If refNodeInsert is missing or invalid.
 */


var checkParams = function checkParams(params) {
  var accountId = params.accountId,
      embedOptions = params.embedOptions,
      embedType = params.embedType,
      options = params.options,
      refNode = params.refNode,
      refNodeInsert = params.refNodeInsert;

  if (!accountId) {
    throw new Error('accountId is required');
  } else if (!isElInDom(refNode)) {
    throw new Error('refNode must resolve to a node attached to the DOM');
  } else if (!isValidEmbedType(embedType)) {
    throw new Error('embedType is missing or invalid');
  } else if (embedType === EMBED_TYPE_IFRAME && options) {
    throw new Error('cannot use options with an iframe embed');
  } else if (embedOptions && embedOptions.tagName !== undefined && !isValidTagName(embedOptions.tagName)) {
    throw new Error("embedOptions.tagName is invalid (value: \"" + embedOptions.tagName + "\")");
  } else if (embedOptions && embedOptions.responsive && embedOptions.responsive.aspectRatio && !/^\d+\:\d+$/.test(embedOptions.responsive.aspectRatio)) {
    throw new Error("embedOptions.responsive.aspectRatio must be in the \"n:n\" format (value: \"" + embedOptions.responsive.aspectRatio + "\")");
  } else if (!isValidRootInsert(refNodeInsert)) {
    throw new Error('refNodeInsert is missing or invalid');
  }
};
/**
 * Normalizes a `refNode` param to an element - or `null`.
 *
 * @private
 * @param  {Element|string} refNode
 *         The value of a `refNode` param.
 *
 * @return {Element|null}
 *         A DOM element or `null` if the `refNode` was given as a string and
 *         did not match an element.
 */


var resolveRefNode = function resolveRefNode(refNode) {
  if (isElInDom(refNode)) {
    return refNode;
  }

  if (typeof refNode === 'string') {
    return document_1.querySelector(refNode);
  }

  return null;
};
/**
 * Initializes a player and returns it.
 *
 * @private
 * @param  {Object} params
 *         A parameters object. See README for details.
 *
 * @param  {Element} embed
 *         An element that will be passed to the `bc()` function.
 *
 * @param  {Function} resolve
 *         A function to call if a player is successfully initialized.
 *
 * @param  {Function} reject
 *         A function to call if a player fails to be initialized.
 *
 * @return {Object}
 *         A success object whose `ref` is a player.
 */


var initPlayer = function initPlayer(params, embed, resolve, reject) {
  var embedId = params.embedId,
      playerId = params.playerId;
  var bc = window_1.bc[playerId + "_" + embedId] || window_1.bc;

  if (!bc) {
    return reject(new Error("missing bc function for " + playerId));
  }

  playerScriptCache.store(params);
  var player;

  try {
    player = bc(embed, params.options); // Add a PLAYER_LOADER property to bcinfo to indicate this player was
    // loaded via that mechanism.

    if (player.bcinfo) {
      player.bcinfo.PLAYER_LOADER = true;
    }
  } catch (x) {
    var message = 'Could not initialize the Brightcove Player.'; // Update the rejection message based on known conditions that can cause it.

    if (params.embedOptions.tagName === EMBED_TAG_NAME_VIDEOJS) {
      message += ' You are attempting to embed using a "video-js" element.' + ' Please ensure that your Player is v6.11.0 or newer in order to' + ' support this embed type. Alternatively, pass `"video"` for' + ' `embedOptions.tagName`.';
    }

    return reject(new Error(message));
  }

  resolve({
    type: EMBED_TYPE_IN_PAGE,
    ref: player
  });
};
/**
 * Loads a player from CDN and embeds it.
 *
 * @private
 * @param  {Object} params
 *         A parameters object. See README for details.
 *
 * @param  {Function} resolve
 *         A function to call if a player is successfully initialized.
 *
 * @param  {Function} reject
 *         A function to call if a player fails to be initialized.
 */


var loadPlayer = function loadPlayer(params, resolve, reject) {
  params.refNode = resolveRefNode(params.refNode);
  checkParams(params);
  var refNode = params.refNode,
      refNodeInsert = params.refNodeInsert; // Store a reference to the refNode parent. When we use the replace method,
  // we'll need it as the location to store the script element.

  var refNodeParent = refNode.parentNode;
  var embed = createEmbed(params); // If this is an iframe, all we need to do is create the embed code and
  // inject it. Because there is no reliable way to hook into an iframe from
  // the parent page, we simply resolve immediately upon creating the embed.

  if (params.embedType === EMBED_TYPE_IFRAME) {
    resolve({
      type: EMBED_TYPE_IFRAME,
      ref: embed
    });
    return;
  } // If we've already downloaded this script or detected a matching global, we
  // should have the proper `bc` global and can bypass the script creation
  // process.


  if (playerScriptCache.has(params)) {
    return initPlayer(params, embed, resolve, reject);
  }

  var script = document_1.createElement('script');

  script.onload = function () {
    return initPlayer(params, embed, resolve, reject);
  };

  script.onerror = function () {
    reject(new Error('player script could not be downloaded'));
  };

  script.async = true;
  script.charset = 'utf-8';
  script.src = urls.getUrl(params);

  if (refNodeInsert === REF_NODE_INSERT_REPLACE) {
    refNodeParent.appendChild(script);
  } else {
    refNode.appendChild(script);
  }
};
/**
 * A function for asynchronously loading a Brightcove Player into a web page.
 *
 * @param  {Object} parameters
 *         A parameters object. See README for details.
 *
 * @return {Promise|undefined}
 *         A Promise, if possible.
 */


var brightcovePlayerLoader = function brightcovePlayerLoader(parameters) {
  var params = _extends$1({}, DEFAULTS, parameters);

  var Promise = params.Promise,
      onSuccess = params.onSuccess,
      onFailure = params.onFailure; // When Promise is not available or any success/failure callback is given,
  // do not attempt to use Promises.

  if (!isFn(Promise) || isFn(onSuccess) || isFn(onFailure)) {
    return loadPlayer(params, isFn(onSuccess) ? onSuccess : function () {}, isFn(onFailure) ? onFailure : function (err) {
      throw err;
    });
  } // Promises are supported, use 'em.


  return new Promise(function (resolve, reject) {
    return loadPlayer(params, resolve, reject);
  });
};
/**
 * Expose a non-writable, non-configurable property on the
 * `brightcovePlayerLoader` function.
 *
 * @private
 * @param  {string} key
 *         The property key.
 *
 * @param  {string|Function} value
 *         The value.
 */


var expose = function expose(key, value) {
  Object.defineProperty(brightcovePlayerLoader, key, {
    configurable: false,
    enumerable: true,
    value: value,
    writable: false
  });
};
/**
 * Get the base URL for players. By default, this will be the Brightcove CDN.
 *
 * @return {string}
 *         The current base URL.
 */


expose('getBaseUrl', function () {
  return urls.getBaseUrl();
});
/**
 * Set the base URL for players. By default, this will be the Brightcove CDN,
 * but can be overridden with this function.
 *
 * @param {string} baseUrl
 *        A new base URL (instead of Brightcove CDN).
 */

expose('setBaseUrl', function (baseUrl) {
  urls.setBaseUrl(baseUrl);
});
/**
 * Get the URL for a player.
 */

expose('getUrl', function (options) {
  return urls.getUrl(options);
});
/**
 * Completely resets global state.
 *
 * This will dispose ALL Video.js players on the page and remove ALL `bc` and
 * `videojs` globals it finds.
 */

expose('reset', function () {
  return env.reset();
}); // Define some read-only constants on the exported function.

[['EMBED_TAG_NAME_VIDEO', EMBED_TAG_NAME_VIDEO], ['EMBED_TAG_NAME_VIDEOJS', EMBED_TAG_NAME_VIDEOJS], ['EMBED_TYPE_IN_PAGE', EMBED_TYPE_IN_PAGE], ['EMBED_TYPE_IFRAME', EMBED_TYPE_IFRAME], ['REF_NODE_INSERT_APPEND', REF_NODE_INSERT_APPEND], ['REF_NODE_INSERT_PREPEND', REF_NODE_INSERT_PREPEND], ['REF_NODE_INSERT_BEFORE', REF_NODE_INSERT_BEFORE], ['REF_NODE_INSERT_AFTER', REF_NODE_INSERT_AFTER], ['REF_NODE_INSERT_REPLACE', REF_NODE_INSERT_REPLACE], ['VERSION', version]].forEach(function (arr) {
  expose(arr[0], arr[1]);
});

/**
 * These prop changes can be handled by an internal player state change rather
 * than a full dispose/recreate.
 *
 * @private
 * @type {Object}
 */

var UPDATEABLE_PROPS = ['catalogSearch', 'catalogSequence', 'playlistId', 'playlistVideoId', 'videoId'];

var logError = function logError(err) {
  /* eslint-disable no-console */
  if (err && console && console.error) {
    console.error(err);
  }
  /* eslint-enable no-console */

};
/**
 * The official React component for the Brightcove Player!
 *
 * This uses `@brightcove/player-loader` to load a player into a React
 * component based on the given props.
 */


var ReactPlayerLoader =
/*#__PURE__*/
function (_React$Component) {
  _inheritsLoose(ReactPlayerLoader, _React$Component);

  /**
   * Create a new Brightcove player.
   *
   * @param {Object} props
   *        Most options will be passed along to player-loader, except for
   *        options that are listed. See README.md for more detail.
   *
   * @param {string} [props.baseUrl]
   *        The base URL to use when requesting a player
   *
   * @param {Object} [props.attrs]
   *        Used to set attributes on the component element that contains the
   *        embedded Brightcove Player.
   *
   * @param {boolean} [props.manualReloadFromPropChanges]
   *        Used to specify if reloading the player after prop changes will be handled manually.
   *
   */
  function ReactPlayerLoader(props) {
    var _this;

    _this = _React$Component.call(this, props) || this;
    _this.refNode = null;

    _this.setRefNode = function (ref) {
      _this.refNode = ref;
    };

    _this.loadPlayer = _this.loadPlayer.bind(_assertThisInitialized(_this));
    return _this;
  }
  /**
   * Loads a new player based on the current props.
   */


  var _proto = ReactPlayerLoader.prototype;

  _proto.loadPlayer = function loadPlayer() {
    var _this2 = this;

    // If there is any player currently loaded, dispose it before fetching a
    // new one.
    this.disposePlayer(); // We need to provide our own callbacks below, so we cache these
    // user-provided callbacks for use later.

    var userSuccess = this.props.onSuccess;
    var userFailure = this.props.onFailure;

    var options = _extends({}, this.props, {
      refNode: this.refNode,
      refNodeInsert: 'append',
      onSuccess: function onSuccess(_ref) {
        var ref = _ref.ref,
            type = _ref.type;

        // If the component is not mounted when the callback fires, dispose
        // the player and bail out.
        if (!_this2.isMounted_) {
          _this2.disposePlayer(ref);

          return;
        } // Store a player reference on the component.


        _this2.player = ref; // Null out the player reference when the player is disposed from
        // outside the component.

        if (type === 'in-page') {
          ref.one('dispose', function () {
            _this2.player = null;
          });
        } // Add a REACT_PLAYER_LOADER property to bcinfo to indicate this player
        // was loaded via that mechanism.


        if (ref.bcinfo) {
          ref.bcinfo.REACT_PLAYER_LOADER = true;
        } // Call a user-provided onSuccess callback.


        if (typeof userSuccess === 'function') {
          userSuccess({
            ref: ref,
            type: type
          });
        }
      },
      onFailure: function onFailure(error) {
        // Ignore errors when not mounted.
        if (!_this2.isMounted_) {
          return;
        } // Call a user-provided onFailure callback.


        if (typeof userFailure === 'function') {
          userFailure(error);
          return;
        } // Fall back to throwing an error;


        throw new Error(error);
      }
    }); // Delete props that are not meant to be passed to player-loader.


    delete options.attrs;
    delete options.baseUrl;
    delete options.manualReloadFromPropChanges; // If a base URL is provided, it should only apply to this player load.
    // This means we need to back up the original base URL and restore it
    // _after_ we call player loader.

    var originalBaseUrl = brightcovePlayerLoader.getBaseUrl();

    if (this.props.baseUrl) {
      brightcovePlayerLoader.setBaseUrl(this.props.baseUrl);
    }

    brightcovePlayerLoader(options);
    brightcovePlayerLoader.setBaseUrl(originalBaseUrl);
  }
  /**
   * Disposes the current player, if there is one.
   */
  ;

  _proto.disposePlayer = function disposePlayer() {
    // Nothing to dispose.
    if (!this.player) {
      return;
    } // Dispose an in-page player.


    if (this.player.dispose) {
      this.player.dispose(); // Dispose an iframe player.
    } else if (this.player.parentNode) {
      this.player.parentNode.removeChild(this.player);
    } // Null out the player reference.


    this.player = null;
  }
  /**
   * Find the index of the `playlistVideoId` prop within the player's playlist.
   *
   * @param  {Object[]} playlist
   *         An array of playlist item objects.
   *
   * @return {number}
   *         The index of the `playlistVideoId` or `-1` if the player has been
   *         disposed, is not using the playlist plugin, or if not found.
   */
  ;

  _proto.findPlaylistVideoIdIndex_ = function findPlaylistVideoIdIndex_(playlist) {
    var playlistVideoId = this.props.playlistVideoId;

    if (Array.isArray(playlist) && playlistVideoId) {
      for (var i = 0; i < playlist.length; i++) {
        var _playlist$i = playlist[i],
            id = _playlist$i.id,
            referenceId = _playlist$i.referenceId;

        if (id === playlistVideoId || "ref:" + referenceId === playlistVideoId) {
          return i;
        }
      }
    }

    return -1;
  }
  /**
   * Create a Playback API callback function for the component's player.
   *
   * @private
   * @param  {string} requestType
   *         The Playback API request type (e.g. "video" or "playlist").
   *
   * @param  {Object} changes
   *         An object. The keys of this object are the props that changed.
   *
   * @return {Function}
   *         A callback for the Playback API request.
   */
  ;

  _proto.createPlaybackAPICallback_ = function createPlaybackAPICallback_(requestType, changes) {
    var _this3 = this;

    return function (err, data) {
      if (err) {
        logError(err);
        return;
      } // If the playlistVideoId changed and this is a playlist request, we
      // need to search through the playlist items to find the correct
      // starting index.


      if (requestType === 'playlist' && changes.playlistVideoId) {
        var i = _this3.findPlaylistVideoIdIndex_(data);

        if (i > -1) {
          data.startingIndex = i;
        }
      }

      _this3.player.catalog.load(data);
    };
  }
  /**
   * Update the player based on changes to certain props that do not require
   * a full player dispose/recreate.
   *
   * @param {Object} changes
   *        An object. The keys of this object are the props that changed.
   */
  ;

  _proto.updatePlayer = function updatePlayer(changes) {
    // No player exists, player is disposed, or not using the catalog
    if (!this.player || !this.player.el()) {
      return;
    } // If the player is using the catalog plugin, we _may_ populate this
    // variable with an object.


    var catalogParams;

    if (this.player.usingPlugin('catalog')) {
      // There is a new catalog sequence request. This takes precedence over
      // other catalog updates because it is a different call.
      if (changes.catalogSequence && this.props.catalogSequence) {
        var callback = this.createPlaybackAPICallback_('sequence', changes);
        this.player.catalog.getLazySequence(this.props.catalogSequence, callback, this.props.adConfigId);
        return;
      }

      if (changes.videoId && this.props.videoId) {
        catalogParams = {
          type: 'video',
          id: this.props.videoId
        };
      } else if (changes.playlistId && this.props.playlistId) {
        catalogParams = {
          type: 'playlist',
          id: this.props.playlistId
        };
      } else if (changes.catalogSearch && this.props.catalogSearch) {
        catalogParams = {
          type: 'search',
          q: this.props.catalogSearch
        };
      }
    } // If `catalogParams` is `undefined` here, that means the player either
    // does not have the catalog plugin or no valid catalog request can be made.


    if (catalogParams) {
      if (this.props.adConfigId) {
        catalogParams.adConfigId = this.props.adConfigId;
      }

      if (this.props.deliveryConfigId) {
        catalogParams.deliveryConfigId = this.props.deliveryConfigId;
      } // We use the callback style here to make tests simpler in IE11 (no need
      // for a Promise polyfill).


      var _callback = this.createPlaybackAPICallback_(catalogParams.type, changes);

      this.player.catalog.get(catalogParams, _callback); // If no catalog request is being made, we may still need to update the
      // playlist selected video.
    } else if (changes.playlistVideoId && this.props.playlistVideoId && this.player.usingPlugin('playlist')) {
      var i = this.findPlaylistVideoIdIndex_(this.player.playlist());

      if (i > -1) {
        this.player.playlist.currentItem(i);
      }
    }
  }
  /**
   * Called just after the component has mounted.
   */
  ;

  _proto.componentDidMount = function componentDidMount() {
    this.isMounted_ = true;
    this.loadPlayer();
  }
  /**
   * Called when the component props are updated.
   *
   * Some prop changes may trigger special behavior (see `propChangeHandlers`),
   * but if ANY prop is changed that is NOT handled, the player will be
   * disposed/recreated entirely.
   *
   * @param  {Object} prevProps
   *         The previous props state before change.
   */
  ;

  _proto.componentDidUpdate = function componentDidUpdate(prevProps) {
    var _this4 = this;

    // Calculate the prop changes.
    var changes = Object.keys(prevProps).reduce(function (acc, key) {
      var previous = prevProps[key];
      var current = _this4.props[key]; // Do not compare functions

      if (typeof current === 'function') {
        return acc;
      }

      if (typeof current === 'object' && current !== null) {
        if (JSON.stringify(current) !== JSON.stringify(previous)) {
          acc[key] = true;
        }

        return acc;
      }

      if (current !== previous) {
        acc[key] = true;
      }

      return acc;
    }, {});

    if (!this.props.manualReloadFromPropChanges) {
      // Dispose and recreate the player if any changed keys cannot be handled.
      if (Object.keys(changes).some(function (k) {
        return UPDATEABLE_PROPS.indexOf(k) === -1;
      })) {
        this.loadPlayer();
        return;
      }
    }

    this.updatePlayer(changes);
  }
  /**
   * Called just before a component unmounts. Disposes the player.
   */
  ;

  _proto.componentWillUnmount = function componentWillUnmount() {
    this.isMounted_ = false;
    this.disposePlayer();
  }
  /**
   * Renders the component.
   *
   * @return {ReactElement}
   *          The react element to render.
   */
  ;

  _proto.render = function render() {
    var props = _extends({
      className: 'brightcove-react-player-loader'
    }, this.props.attrs, {
      ref: this.setRefNode
    });

    return React.createElement('div', props);
  };

  return ReactPlayerLoader;
}(React.Component);

export { ReactPlayerLoader as R };
