document.domain = 'nba.com';
(function(){

    if (Embedded == null || typeof(Embedded) != "object") {
        /**
         * Responsible for common functions of Embedded objects
         *
         * @classDescription	Embedded object
         * @return {Embedded}	Returns a new Embedded object
         * @type {Object}
         * @constructor
         */
        var Embedded = window.Embedded = function(){
            this.initialize();
        }
        
        /**
         * Configuration object for Embedded
         *
         * @memberOf Embedded
         * @type {Object} Configuration parameters for Embedded objects
         */
        Embedded.config = {
            /** @type {Regex} Pattern for matching Embedded scripts */
            embedScriptPattern: /embedded\.js(?:(?:\?([^#]+)#?.*)|(?:#library))/i,
            /** @type {Regex} Pattern for extracting query strings */
            qsPattern: /^[^\?]+\?([^#]+)(?:#[^#]+)?$/i,
            /** @type {String} Template string for embedded iframes */
            htmlTemplate: '<iframe id="nba_evp_iframe_#{_ct}" name="nba_evp_iframe_#{_ct}" src="http://www.nba.com/.element/js/1.0/evp/src/host.html?vid=#{_vid}" width="#{_w}" height="#{_h}" frameborder="0" scrolling="no"></iframe>',
            /** @type {Object} Available sizes for video */
            sizes: {
                /** @type {Number} Small */
                sm: 300,
                /** @type {Number} Medium */
                md: 418,
                /** @type {Number} Large */
                lg: 577
            },
            /** @type {Number} Aspect ratio for embedded media */
            aspectRatio: 16 / 9,
			/** @type {Number} Added padding to computed height for fixed-height control bar */
			controlBarHeight: 31,
            /** @type {Array} Allowable domains for embedding */
            domains: [".nba.com"]
        };
        
        /**
         * Returns the slug for a given video identifier
         *
         * @param {String}	vid	The unique video identifier
         * @return {String} 	The slug for the video
         */
        Embedded.getSlug = function(vid){
            /** @type {Regex} Pattern for matching slugs */
            var slugPattern = /^(?:[^\/]+\/)+([^\/]+$)/;
            var match = vid.match(slugPattern);
            if (match && match[1]) {
                var slug = match[1];
                if (slug.match(/\./)) {
                    slug = slug.substring(0, slug.lastIndexOf("."));
                }
                return slug;
            }
            return null;
        };
        
        /**
         * Determines if the current domain is allowed to embed video
         *
         * @return {Boolean}	True if the Embed script is allowed on the embedding domain
         */
        Embedded.isDomainAllowed = function(domain){
            if (domain == "") {
                // probably a local file access
                return true;
            }
            var isAllowed = false;
            for (var i = 0; i < Embedded.config.domains.length; i++) {
                domain = domain.toLowerCase();
                isAllowed = domain.indexOf(Embedded.config.domains[i].toLowerCase()) >= 0;
                if (isAllowed) {
                    break;
                }
            }
            return isAllowed;
        }
        
        /**
         * Finds all script tags in the current page
         *
         * @return {Array}		An array of script tags
         */
        Embedded.findScripts = function(){
            var scripts = document.getElementsByTagName("script");
            return scripts;
        };
        
        /**
         * Determines if a script node is an Embedded script or not
         *
         * @param {Node}	script	Script node
         * @return {Boolean}		True if the script node is an Embedded script
         */
        Embedded.isEmbedScript = function(script){
            if (script && script.src && Embedded.config.embedScriptPattern.test(script.src)) {
                return true;
            }
            return false;
        };
        
        /**
         * Returns all Embedded script nodes in the current document
         *
         * @return {Array}		An array of Embedded script nodes
         */
        Embedded.findEmbeddedScripts = function(){
            var scripts = Embedded.findScripts();
            var embeds = new Array();
            if (scripts && scripts.length > 0) {
                for (var i = 0; i < scripts.length; i++) {
                    if (Embedded.isEmbedScript(scripts[i])) {
                        embeds.push(scripts[i]);
                    }
                }
            }
            return embeds;
        };
        
        /**
         * Returns the current Embedded script node. This should be the last
         * valid Embedded script node in the document at the time of execution.
         * Remember that this can execute inline on an incomplete DOM.
         *
         * @exception {String}	Thrown if no Embedded script node could be found
         * @return {Node}		The current Embedded script node
         */
        Embedded.getCurrentScript = function(){
            var embeds = Embedded.findEmbeddedScripts();
            if (embeds && embeds.length > 0) {
                return embeds[embeds.length - 1];
            }
            throw "Unable to find this script instance!";
        };
        
        /**
         * Determines if the current script is running in Library mode.
         * In library mode, a new Embedded object is not auto-instantiated.
         * This library mode provides support for the host HTML page.
         *
         * @return {Boolean}		True if this script should function as a library
         */
        Embedded.isLibrary = function(){
            var script = Embedded.getCurrentScript();
            var src = script.src;
            var qs = src.match(Embedded.config.embedScriptPattern);
            if (qs && qs[0] && !qs[1]) {
                return true;
            }
            return false;
        }
        
        /**
         * Returns the query string from the given script node
         *
         * @param {Node}	script	The script node to retrieve the query string from
         * @return {String}			The query string, or and empty string
         */
        Embedded.getScriptQueryString = function(script){
            var src = script.src;
            var qs = src.match(Embedded.config.embedScriptPattern);
            if (qs && qs[1]) {
                return qs[1];
            }
            return '';
        };
        
        /**
         * Splits a query string into key/value sets
         *
         * @param {String}	qs	The query string to split
         * @return {Array}		An array of key/value string pairs
         */
        Embedded.getParamPairsAsArray = function(qs){
            if (qs) {
                return qs.split('&');
            }
            return [];
        };
        
        /**
         * Splits parameter pairs from an array into a hash object
         *
         * @param {Array}	pairs	An array of key=value string parameter sets
         * @return {Object}			A hash of the parameters
         */
        Embedded.getParamsAsHash = function(pairs){
            // TODO: support multiple instances of param
            var hash = {};
            for (var i = 0; i < pairs.length; i++) {
                var pair = pairs[i].split('=');
                if (pair[0] && pair[1]) {
                    hash[pair[0]] = decodeURIComponent(pair[1]);
                }
            }
            return hash;
        }
        
        /**
         * Convenience function to return the current script's params as a hash.
         * If the current script is running in Library mode, this function will
         * return a hash of parameters from window.location instead.
         *
         * @param {String}	[url]	An optional url to strip the query string from
         * @return {Object} 		Hash of parameters from the current script tag or
         * 							document url.
         */
        Embedded.getParamHash = function(url){
            var qs = '';
            if (url) {
                if (Embedded.config.qsPattern.test(url)) {
                    qs = Embedded.config.qsPattern.exec(url)[1];
                }
            }
            else {
                try {
                    var script = Embedded.getCurrentScript();
                    qs = Embedded.getScriptQueryString(script);
                } 
                catch (e) {
                }
                if (Embedded.isLibrary() || !qs) {
                    if (window.location.search) {
                        qs = window.location.search.match(/^\?(.+)$/i)[1];
                    }
                }
            }
            var pairs = Embedded.getParamPairsAsArray(qs);
            return Embedded.getParamsAsHash(pairs);
        }
        
        Embedded.prototype = {
            /** @type {Object} Internal storage of parameters */
            _paramHash: null,
            /** @type {Number} */
            _w: Embedded.config.sizes.sm,
            /** @type {Number} */
            _h: Math.floor(Embedded.config.sizes.sm / Embedded.config.aspectRatio) + Embedded.config.controlBarHeight,
            /** @type {String} */
            _vid: null,
			_ct: Math.random().toString(),
            
            /**
             * Ensures that this video object is valid and complete.
             * A video is valid if it has all the information
             * necessary to actually perform the embed.
             *
             * @return {boolean}	True if the Video is valid
             */
            isValid: function(){
                var w = parseInt(this._w);
                var h = parseInt(this._h);
                if (!isNaN(w) && w > 0 && !isNaN(h) && h > 0 && this._vid && Embedded.getSlug(this._vid)) {
                    return true;
                }
                return false;
            },
            
            /**
             * Checks to see if this instance has a specific parameter
             *
             * @param {String}	param 	Name of the param to check for
             * @return {Boolean}		True if the Video has the parameter
             */
            hasParam: function(param){
                var val = this._paramHash[param];
                if (val != undefined) {
                    return true;
                }
                return false;
            },
            
            /**
             * Fetches the value of a named parameter
             *
             * @param {Object}	param	Name of the param to fetch
             * @return {String, undefined}	Returns the value of the parameter as a String, or undefined if it does not exist
             */
            getParam: function(param){
                if (this.hasParam(param)) {
                    var val = this._paramHash[param];
                    return val;
                }
                return undefined;
            },
            
            /**
             * Filters a template string, using this instance for the token values.
             *
             * @param {String}	template	The template string to filter
             * @return {String}				The filtered template
             */
            filter: function(template){
                while (template && /#{.+?}/.test(template)) {
                    var token = template.match(/#{(.+?)}/)[1];
                    template = template.replace(/#{(.+?)}/, encodeURIComponent(this[token]));
                }
                return template;
            },
            
            /**
             * Generates an HTML representation of this Embeddable
             *
             * @return {String}		HTML for this object
             */
            toHTML: function(){
                if (this.isValid()) {
                    return this.filter(Embedded.config.htmlTemplate);
                }
                return '';
            },
            
            /**
             * Instance initializer. Executed automatically by constructor.
             *
             * @return {void}
             */
            initialize: function(){
                this._paramHash = Embedded.getParamHash();
                if (this.getParam('size') && /sm|md|lg/.test(this.getParam('size'))) {
                    switch (this.getParam('size')) {
                        case 'sm':
                            this._w = Embedded.config.sizes.sm;
                            break;
                        case 'md':
                            this._w = Embedded.config.sizes.md;
                            break;
                        case 'lg':
                            this._w = Embedded.config.sizes.lg;
                            break;
                    }
                    
                }
                else 
                    if (this.getParam('w')) {
                        this._w = parseInt(this.getParam('w'));
                    }
                this._h = Math.floor(parseInt(this._w) / Embedded.config.aspectRatio) + Embedded.config.controlBarHeight;
                this._vid = this.getParam('vid');
            }
        };
    };
    
    if (!Embedded.isLibrary(Embedded.getCurrentScript())) {
        if (Embedded.isDomainAllowed(window.location.host)) {
            var v = new Embedded();
            document.write(v.toHTML());
        }
    }
})();

