// Init Kyte only if not already defined.
if(typeof Kyte == "undefined") var Kyte = {};
if(typeof Kyte.Utility == "undefined") Kyte.Utility = {
    getMapFromQueryString:function(value) { // Passing no value (undefined) will get it from the browser.
        var n = new Object();

        if(value==undefined) {
            var href = location.href;
            var hi = href.indexOf("#"); // Trim off the hash first.
            if(hi!=-1) href = href.substring(0,hi);

            var qmi = href.indexOf("?");
            if(qmi!=-1) value = href.substring(qmi+1);
        }

        if(value) {
            var p = value.split("&");
            for(var i=0;i<p.length;++i) {
                var entry = p[i].split("=");
                if(entry.length==2)
                    n[entry[0]] = Kyte.Utility.convertSpecialStringValues(decodeURIComponent(entry[1]));
            }
        }
        return n;
    },
    getQueryStringFromMap:function(value,keys) {
        var s = "";
        function a(k) {
            var v = value[k];
            if(v!=undefined)
                s += (s.length==0?"":"&") + k + "=" + encodeURIComponent(v);
        }
        if(value) {
            if(typeof keys=="string") keys = keys.split(",");
            if(keys!=null && keys.constructor==Array) for(var i=0;i<keys.length;++i) a(keys[i]);
            else for(var key in value) a(key);
        }
        return s;
    },
    convertSpecialStringValues:function(value) {
        if(typeof value == "string") {
            switch(value.replace(/^s+|s+$/g,"").toLowerCase()) {
                case "true": return true;
                case "false": return false;
                case "null": return null;
                case "undefined": return undefined;
            }
        }
        return value;
    }
};

if(typeof Kyte.Flash == "undefined") {
    Kyte.Flash = {
        Version:function(v){
            if(typeof v == "number") v = [v];
            else if(typeof v == "string") v = v.split(".");
            this.major = v[0] != null ? parseInt(v[0]) : 0;
            this.minor = v[1] != null ? parseInt(v[1]) : 0;
            this.rev = v[2] != null ? parseInt(v[2]) : 0;
        },
        _currentVersion:null
    };
    Kyte.Flash.Version.prototype = {
        isValid:function(v) {
            //noinspection FallthroughInSwitchStatementJS
            switch(typeof v) {
                case "object":
                    if(v.constructor != Array) break;
                case "number":
                case "string":
                    v = new Kyte.Flash.Version(v);
            }
            if(this.major < v.major) return false;
            if(this.major > v.major) return true;
            if(this.minor < v.minor) return false;
            return this.minor>v.minor || this.rev>=v.rev;
        },
        toString:function() {
            return this.major+"."+this.minor +"."+this.rev;
        }
    };
    Kyte.Flash.getCurrentVersion = function() {
        // Only initialize the player object when necessary.
        if(Kyte.Flash._currentVersion) return Kyte.Flash._currentVersion;
        var v = new Kyte.Flash.Version(0), axo;
        // Mozilla Browsers Etc.
        if(navigator.plugins && navigator.mimeTypes.length){
            var x = navigator.plugins["Shockwave Flash"], desc = x?x["description"]:null;
            if(desc) v = new Kyte.Flash.Version(desc.replace(/([a-zA-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, "."));
        }
        // Windows CE
        else if (navigator.userAgent && navigator.userAgent.indexOf("Windows CE") >= 0) {
            axo = 1;
            var counter = 3;
            while(axo) {
                //noinspection JSUnusedLocalSymbols
                try {
                    counter++;
                    axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+ counter);
                    v = new Kyte.Flash.Version(counter);
                } catch (ex) { axo = null; }
            }
        }
        // ActiveX
        else {
            //noinspection JSUnusedLocalSymbols
            try{ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7"); }
            catch(ex){
                //noinspection JSUnusedLocalSymbols
                try {
                    axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
                    v = new Kyte.Flash.Version("6.0.21");
                    axo.AllowScriptAccess = "always";
                } catch(ex) { if (v.major == 6) return v; }
                //noinspection JSUnusedLocalSymbols
                try {
                    axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
                } catch(ex) {}
            }
            if (axo != null) {
                v = new Kyte.Flash.Version(axo["GetVariable"]("$version").split(" ")[1].split(","));
                v.isActiveX = true;
            }
        }
        // Cache for re-use.
        Kyte.Flash._currentVersion = v;

        return v;
    };
    Kyte.Flash.minimumVersion = navigator.platform.indexOf("Mac")==0?"10.0.22":"10.0.22";
    Kyte.Flash.isValidVersion = function(v) {
        if(v==null) v = Kyte.Flash.minimumVersion;
        return Kyte.Flash.getCurrentVersion().isValid(v);
    };
    Kyte.Flash.HTML = {
        encodeAttribute:function(str) { return String(str).replace(/"/g,"&quot;").replace(/&/g,"&amp;"); },
        object:function(src,width,height,params,id) {
            if(params==null) params = {};
            else if(typeof params=="string") params = Kyte.Utility.getMapFromQueryString(params);
            params.allowScriptAccess = "always";
            params.allowFullScreen = "true";
            if(Kyte.Flash.getCurrentVersion()["isActiveX"]) params.movie = src; // Attempt to resolve 206 response code when no cache is present by only including for ActiveX.
            var paramString = "";
            for(var key in params) paramString += '<param name="'+Kyte.Flash.HTML.encodeAttribute(key)+'" value="'+Kyte.Flash.HTML.encodeAttribute(params[key])+'"/>';
            return '<object '+(id==null?"":('id="'+id+'" '))+'type="application/x-shockwave-flash" style="display:block;margin:0" width="'+width+'" height="'+height+'"'+(Kyte.Flash.getCurrentVersion()["isActiveX"]?'':(' data="'+src+'"'))+'>'+paramString+'</object>';
        },
        embed:function(src,width,height,params,id) {
            if(params==null) params = {};
            else if(typeof params=="string") params = Kyte.Utility.getMapFromQueryString(params);
            params.allowScriptAccess = "always";
            params.allowFullScreen = "true";
            var paramString = "";
            for(var key in params) paramString += ' '+Kyte.Flash.HTML.encodeAttribute(key)+'="'+Kyte.Flash.HTML.encodeAttribute(params[key])+'"';
            return '<embed '+(id==null?"":('id="'+id+'" '))+'type="application/x-shockwave-flash" style="display:block;margin:0" width="'+width+'" height="'+height+'" src="'+src+'"'+paramString+'></embed>';
        },
        render:function(src,width,height,params,noflashElement,id) {
            if(typeof noflashElement == "string")
                noflashElement = document.getElementById(noflashElement);

            if(Kyte.Flash.isValidVersion()) {
                var html = Kyte.Flash.HTML.object(src,width,height,params,id);

                // The noflashElement provided will be hidden as a fallback to having it's contents replaced.
                if(noflashElement) {
                    if(noflashElement.innerHTML) {
                        noflashElement.innerHTML = html;
                        html = null;
                    } // Solve for potential issues. Where nonflashElement is cannot be replaced.
                    else if(noflashElement.style && noflashElement.style.display)
                        noflashElement.style.display = "none";
                }

                if(html)
                    document.write(html);

            }
            else if(!noflashElement) document.write('<div style="width:'+width+'px;height:'+height+'px;'+(params["bgcolor"]?("background-color:"+params["bgcolor"]):"")+'"><a href="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash&amp;promoid=BIOW" target="_blank"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get the latest Adobe Flash Player" hspace="30" vspace="30" border="0"/></a></div>');

        }
    };
}

if(typeof Kyte.Embed == "undefined") {
    Kyte.Embed = {
        path:"http://www.kyte.tv",
        file:"/f/",
        count:0,
        instances:{},
        getPath:function() { return typeof Kyte.path == "undefined" ? Kyte.Embed.path : Kyte.path; },
        getInstanceID:function(player,id) {
            if(id==null || Kyte.Embed.instances[id]==null) {
                ++(Kyte.Embed.count);
                if(id==null) id = "KyteApplication_"+(Kyte.Embed.count);
                player.id = id;
                Kyte.Embed.instances[id] = player;
            }
            return id;
        },
        init:function(id) {
            Kyte.Embed.instances[id].init();
        },
        prepVariables:function(variables) {
            if(variables==null)
                variables = new Object();
            else if(typeof variables=="string")
                variables = Kyte.Utility.getMapFromQueryString(variables);
            else for(var key in variables) {
                var v = variables[key], vv = Kyte.Utility.convertSpecialStringValues(v);
                if(v!=vv) variables[key] = vv;
            }
            return variables;
        },
        processSpecialVariables:function(params,variables) {
            variables = Kyte.Embed.prepVariables(variables);
            function extract(n) {
                var r = variables[n];
                if(r!=undefined && r!=null) {
                    params[n] = r;
                    delete variables[n];
                }
            }
            extract("bgcolor");
            extract("wmode");
            extract("quality");
            extract("align");
            extract("valign");
            extract("allowScriptAccess");
            extract("allowFullScreen");

            return variables;
        },
        extendClass:function(subClass, baseClass) {
           function inheritance() {};
           inheritance.prototype = baseClass.prototype;

           subClass.prototype = new inheritance();
           subClass.prototype.constructor = subClass;
           subClass.baseConstructor = baseClass;
           subClass.superClass = baseClass.prototype;
        }

    };

    Kyte.FlashApplication = function(
            src,
            width,height,
            params, // [Optional]
            noflashElement, // [Optional] Element which the player will insert into.  Can be either the element or its ID.
            id // [Optional] DOM ID the player will use instead of autogenerated.
        ) { // Aux vars can be a query string, or hash map.
        id=Kyte.Embed.getInstanceID(this,id);
        var me = this;
        me.renderArguments = {src:src,width:width,height:height,params:params,noflashElement:noflashElement,id:id};
        Kyte.Flash.HTML.render(src,width,height,params,noflashElement,id);

        me["addEventListener"]("Player.UpdateDimensions",function(event){
            var d = event["data"];
            me.setSize( d.width, d.height, d["stageWidth"], d["stageHeight"] );
        });

        me["addEventListener"]("API.Extend",function(event){
            var d = event["data"], methodPath = d["methodName"], groups = methodPath.split("."), node = me;
            var methodName = groups.pop();
            for (var n=0;n<groups.length;n++) { // Extend groupings
              var gn = groups[n], group = node[gn];
              if(!group) node[gn] = group = {};
              node = group;
            }

            var params = d["params"];
            node[methodName] = function() {
              var args = new Array();
              args.push( methodPath );
              if(params) for (var i=0;i<params.length;++i) args.push(params[i]);
              for (var i=0;i<arguments.length;++i) args.push(arguments[i]);
              return me.execute(d["exposedFunctionName"], args).value;
            };
        });
        function onWindowUnload() { me.execute("destroy"); }
        if (window.addEventListener)
            window.addEventListener("unload",onWindowUnload,false);
        else if(window.attachEvent)
            window.attachEvent("onunload",onWindowUnload);
    };

    Kyte.FlashApplication.prototype = {
        // facilitates queing and safe execution of calls into the player.
        id:null,
        _element:null,
        initialized:false,
        init:function() {
            if(!this.initialized) {
                this.queueExecute();
                this.onInit();
                this.initialized = true;
            }
        },
        getElement:function() {
          if(this._element==null) this._element = document.getElementById(this.id);
          return this._element;
        },
        setSize:function(w,h,stageWidth,stageHeight) {
            // w & h are the requested width and height compared to the inner width...
            // NOTE: stageWidth and stageHeight are used to compensate for browser zooming...
            var element = this.getElement();
            function setDimension(name,value,inner) {
              if(!isNaN(value)) {
                var measured = element[name];
                if(!isNaN(inner))
                  value *= Math.round(measured/inner);
                if(measured!=value)
                  element.setAttribute(name, value);
              }
            }
            setDimension("width",w,stageWidth);
            setDimension("height",h,stageHeight);
        },
        onInit:function() {}, // Overrideable handler for when the player is initialized.
        execute:function(methodname,params) { // params can be an array.  If the desired single param is an array, wrap in another [array].

            var result = {value:undefined,success:false,error:undefined};
            try {
                //noinspection JSUnusedLocalSymbols
                var element = this.getElement(), i;
                if(params == undefined) params = [];
                else if(params==null || params.constructor != Array) { // Allow for extended parameters.
                    var p = new Array();
                    for (i=1;i<arguments.length;++i) p.push(arguments[i]);
                    params = p;
                }
                var paramString = "";
                for(i=0;i<params.length;++i) paramString += (paramString.length==0?"":",") + "params["+i+"]";
                result.value = eval("element."+methodname+"("+paramString+")");
                result.success = true;
            }
            catch (ex) {
                result.error = "ERROR - Kyte.FlashApplication: "+this.id+"."+methodname+"("+params.join(",")+")\n" + ex.message;
                if(!this.initialized)
                    result.error += "\nWARNING - Synchronous 'execute' called before initialization.\nUse asynchronous 'queue' method if uncertain of initialization state. ";
            }

            return result;
        },
        _queue:null,
        _queueThreadId:0,
        queue:function(methodname,params,callback) { // Use a value or array of values to represent the arguments passed in.
            var me=this;
            if(me._queue==null)
                me._queue = new Array();
            me._queue.push({methodname:methodname,params:params,callback:callback});
            if(me.initialized && me._queueThreadId==0) // If not initialized, queueExecute will occur when init is called.
                me._queueThreadId = setTimeout(function(){me.queueExecute();},0);
        },
        // Will cause the queued requests to be called immediately.
        queueExecute:function(player) {
            if(player==null)
                player = this;
            else if(typeof player == "string")
                player = Kyte.Embed.instances[player]; // Allow for static usage.

            if(player._queueThreadId)
                clearTimeout(player._queueThreadId); // clear any existing timeout
            player._queueThreadId = 0;

            // Execute current callbacks.
            var currentQueue = player._queue;
            player._queue = null; // replace existing array for re-entrant safety
            var len = currentQueue.length;

            for(var i=0;i<len;++i) {
                var c = currentQueue[i];
                if(c) {
                    var result = player.execute(c.methodname,c.params);
                    if(c.callback)
                        c.callback(result);
                    currentQueue[i] = null; // (eliminated potential double call);
                }
            }

        },
        _eventListeners:null,
        addEventListener:function(type,callback) {
            var listeners = this._eventListeners;
            if(!listeners) this._eventListeners = listeners = new Object();
            var a = listeners[type];
            if(a==null) listeners[type] = a = new Array();
            for(var i=0;i<a.length;++i)
                if(a[i]==callback)
                    return;

            a.push( callback );
            this.queue("registerEventListener",[type,"Kyte.Embed.instances."+this.id+".dispatchEvent"]);
        },
        removeEventListener:function(type,callback) {
            var a = this._eventListeners ? this._eventListeners[type] : null;
            if(a) {
                var i = a.length;
                while(i>0) {
                    --i;
                    if( a[i] == callback )
                        a.splice( i, 1 );
                }
            }
            if(a.length==0)
                this.queue("unregisterEventListener",[type,"Kyte.Embed.instances."+this.id+".dispatchEvent"]);

        },
        postEvent:function(event,handler) {
            // MF-3580 Make this a separate function to create a new closure for each setTimeout call!
            setTimeout(function(){handler(event);},0);
        },
        dispatchEvent:function(event) {
            event.source = this;
            var a = this._eventListeners ? this._eventListeners[event.type] : null;
            if(a) for(var i=0;i<a.length;++i) // Ensure listeners don't hang the app.
                this.postEvent(event,a[i]);
        }
    };


    Kyte.Application = function(
            src,
            width,height, // These are the defaults, but could be overridden by coinciding flashVars.
            params, // [Optional]
            noflashElement, // [Optional] Element which the player will insert into.  Can be either the element or its ID.
            id // [Optional] DOM ID the player will use instead of autogenerated.
        ) { // Aux vars can be a query string, or hash map.
        var variables = Kyte.Embed.processSpecialVariables(params,params?params["flashVars"]:null);

        variables["domId"] = id = Kyte.Embed.getInstanceID(this,id);
        //noinspection JSUnusedLocalSymbols
        try{ variables["userAgent"] = window.navigator.userAgent; } catch(ex){};
        //noinspection JSUnusedLocalSymbols
        try{ variables["referrerUrl"] = location.href; } catch(ex){};


        if(variables["width"]) {
            width = variables["width"];
            delete variables["width"];
        }
        if(variables["height"]) {
            height = variables["height"];
            delete variables["height"];
        }

        params["flashVars"] = Kyte.Utility.getQueryStringFromMap(variables);

        this.setUri = this.setURI = function(uri) { this.queue("setUri",uri);};

        Kyte.Application.baseConstructor.call(this,src,width,height,params,noflashElement,id);
    };
    Kyte.Embed.extendClass(Kyte.Application,Kyte.FlashApplication);

    Kyte.UriApplication = function(appKey,width,height,uri,variables,noflashElement,id){
        var params = {}, path = Kyte.Embed.getPath()+Kyte.Embed.file;
        variables = Kyte.Embed.processSpecialVariables(params,variables);

        variables["appKey"] = appKey;
        variables["uri"] = uri;

        params["flashVars"] = variables;

        Kyte.UriApplication.baseConstructor.call(this,path+uri+"&"+Kyte.Utility.getQueryStringFromMap(variables,"appKey,embedId"),width,height,params,noflashElement,id);
    };
    Kyte.Embed.extendClass(Kyte.UriApplication,Kyte.Application);

    Kyte.Player = function(
            uri, // [Required] Where the player content starts.
            variables, // [Optional] Extra initialization variables to pass to the player.
            noflashElement, // [Optional] Element which the player will insert into.  Can be either the element or its ID.
            id // [Optional] DOM ID the player will use instead of autogenerated.
        ) { // Aux vars can be a query string, or hash map.

        // NOTE: If supplied in the embed, WIDTH & HEIGHT VALUES ARE OVERRIDDEN IN Kyte.Application.
        var width = 425, height = 425;
        variables = Kyte.Embed.prepVariables(variables);

        //noinspection FallthroughInSwitchStatementJS
        switch(variables["layoutMode"]) {
            case "branded":
            case "premium":
                 // Legacy. Use premium=true.
                delete variables["layoutMode"];
                variables["premium"] = true; // Handled after switch.
                // Allow fallthrough....
            default:
                height = 445; break;
            case "wide":
                width = 850; break;
            case "tall":
                height = 850; break;
        }

        if(height<500 && variables["premium"])
            height += 55;

        var me = this;
        Kyte.Player.baseConstructor.call(me,"MarbachViewerEmbedded",width,height,uri,variables,noflashElement,id);

        // Possible "element" values: "Chat", "ShowBrowser", "Producer", "Kytefeed", "Menu", "Flag".
        me.display = function(element,open) { if(open==null) open=true; me.queue("display",[element,open]);};

        // Deprecated... Use: display(element).
        me.creatorPaneOpen = function(open) { me.display("Producer",open); };
        me.chatPaneOpen = function(open) { me.display("Chat",open); };

    };
    Kyte.Embed.extendClass(Kyte.Player,Kyte.UriApplication);

    Kyte.ChannelBuilder = function(uri,variables,noflashElement,id){
        Kyte.ChannelBuilder.baseConstructor.call(this,"MarbachChannelCreator",960,535,uri,variables,noflashElement,id);
    };
    Kyte.Embed.extendClass(Kyte.ChannelBuilder,Kyte.UriApplication);

    Kyte.ShowBuilder = function(uri,variables,noflashElement,id) {
        Kyte.ShowBuilder.baseConstructor.call(this,"MarbachShowCreator",960,535,uri,variables,noflashElement,id);
    };
    Kyte.Embed.extendClass(Kyte.ShowBuilder,Kyte.UriApplication);

    Kyte.Chat = function(uri,variables,noflashElement,id) {
        Kyte.Chat.baseConstructor.call(this,"MarbachChat",425,445,uri,variables,noflashElement,id);
    };
    Kyte.Embed.extendClass(Kyte.Chat,Kyte.UriApplication);

    Kyte.ShowComments = function(uri,variables,noflashElement,id) {
        Kyte.ShowComments.baseConstructor.call(this,"MarbachShowComments",425,445,uri,variables,noflashElement,id);
    };
    Kyte.Embed.extendClass(Kyte.ShowComments,Kyte.UriApplication);


    Kyte.MiniProducer = function(uri,variables,noflashElement,id) {
        Kyte.MiniProducer.baseConstructor.call(this,"MarbachMiniShowCreator",425,445,uri,variables,noflashElement,id);
    };
    Kyte.Embed.extendClass(Kyte.MiniProducer,Kyte.UriApplication);

    Kyte.ShowBrowser = function(uri,variables,noflashElement,id) {
        var width = 425, height = 425;
        variables = Kyte.Embed.prepVariables(variables);
        var mode = variables["showBrowserMode"] + "";

        if(mode=="condensed") height = 132;
        else if(mode.indexOf("vertical")==-1) height = 183;

        Kyte.ShowBrowser.baseConstructor.call(this,"MarbachBrowser",width,height,uri,variables,noflashElement,id);
    };
    Kyte.Embed.extendClass(Kyte.ShowBrowser,Kyte.UriApplication);

}
