/**
* ENVIRONMENT HANDLER
* Desc:    The core settings for the other functions within this script
*          It's basically so we can quickly set path names etc and we know
*          all other functions here will use them
**/

var myEnv = new function(){

    // Get domain of the core by finding the first core stylesheet we use
    this.corePath   = "";
    for(i=0;i<document.styleSheets.length;i++){
        var ss = document.styleSheets[i].href;
        if(ss.indexOf("beetleblox")){
            ss = ss.replace("http://","");
            ss = ss.split("/");
            this.corePath = "http://"+ss[0];
            break;
        }
    }
    this.imgPath    = this.corePath+"/images"; // Images for the core
    this.ieVersion  = navigator.appVersion.indexOf("MSIE")?parseFloat(navigator.appVersion.substr((navigator.appVersion.indexOf("MSIE")+5),1)):0;
    this.browserIE6 = ((this.browser == "IE") && (this.ieVersion < 7))?true:false;
    this.docType    = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
                    + '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-GB" lang="en">';

    // Get Env Property
    this.get = function(id){
        if(typeof(this[id]) != "undefined" && typeof(this[id]) != "function"){
            return this[id];
        }
        return "";
    }

    // Get window height fix for 'webkit' engines.
    // This is required in instances where absolute positioning
    // has been used to create the layout. In the 'webkit' browser styles they only take into
    // account certain elements and it can damage mootools window.getScroll dimensions.
    this.fixWindowScrollHeight = function(param){
        if(Browser.Engine.webkit && $("webkit_height_fix")){
            return $("webkit_height_fix").getCoordinates().bottom;
        } else {
            return window.getScrollHeight();
        }
        return o;
    }
}



/**
* CREATE CLICKABLE BOXES
* Coverts a box that contains a link into a completely clickable area and can hide the original link if required.
* Example HTML : <div class='clickable'>This is some text and then we have a <a href='' class='clickable-backup'>Learn more</a> button.</div>
* This function would make the entire <DIV> clickable and optionally remove the link that contains the class 'clickable-backup'.
*/
var myClickBoxes = new function(){
    this.start = function(parentElement,removeOriginalLink){
        if(!parentElement){parentElement = "";}
        if(removeOriginalLink !== false){removeOriginalLink = true;}

        $$(parentElement+".clickable").each(function(el){
            elurl  = el.getElements(parentElement+"a.clickable-backup")[0];
            if(removeOriginalLink === true){
                elurl.backup.setStyle("display","none");
            }
            el.setStyle("cursor","pointer");
            el.addEvents({
                "mouseenter" : function(){
                    this.removeClass("clickable");
                    this.addClass("clickable_hover");
                },
                "mouseleave" : function(){
                    this.removeClass("clickable_hover");
                    this.addClass("clickable");
                },
                "mousedown" : function(){
                    if(this.getProperty("onclick")){
                        this.removeEvents();
                        this.addEvent("click",this.onclick);
                        this.fireEvent("click");
                    } else {
                        window.location.href=this.getProperty("href");
                    }
                }.bind(elurl)
            });
        });
    }
}

/**
* AJAX HANDLER
* Desc        :    Handles all types of ajax requests
*                It can be attached to form buttons, <a>links and can be called directly from other scripts.
*
*
* Usage        :    The following examples will place the returned HTML into the element with the id of "myDivId" (where specified)
* Params    :    @sourceObject        =    Is set to either 'this' if on submit button or <a> link. Otherwise it can be set to a path to a    url.
*                @destinationId        =    Either the physical object or the string id of the object.
*                @responseFunction    =    The function to use as the alternative response after the ajax call has been made
*                @loaderFunction        =    An additional function that can be run straight after the "loading" dialogue shows. This function
*                                        would run before the ajax call.
*
*                Example 01 - link    : <a href="/go/somewhere.com" onclick="return myAjax.doRequest(this,'myDivId')">My Link</a>
*                Example 02 - submit    : <input type="submit" value="Submit Form" onclick="return myAjax.doRequest(this,'myDivId')" />
*                Example 03 - script : myAjax.doRequest("/go/somewhere.com","myDivId");
*
*
*                What's the "onComplete function all about?
*                ==========================================
*                well.. this function is used when you want to run javascript from the html content that was called.
*                So basically, aswell as returning HTML you can also return additional javascript that can run AFTER the HTML
*                has been placed in its final location. Have a look at the class "class.javascript.php" in the classes repository and
*                find the function myAjaxComplete() which you can run in order to apply additional script to run. It's good because
*                you don't have to bulk up your initial Javascript includes before making these kind of calls.
*
**/
var myAjax = new function ajaxObject(){

    // Turn on debugging
    this.debug = false;

    // On complete function
    // This is run at the very VERY end of any myAjax, even after
    // the doResponse() function is called. It is useful for running additional Javascript
    // that does something to the content AFTER it is placed into its destination.
    // This means you can set the Javascript on the loaded content side.
    this.onComplete = function(){}

    // The ajaxControl frame
    this.ajaxFrame = null;

    // Main request function
    this.doRequest = function(sourceObject,destinationId,responseFunction,loaderFunction){
        // Remove any existing ajax control frame
        this.removeAjaxControlFrame();

        // Reset finished
        // Shouldn't be set yet anyway
        this.onComplete = function(){}

        // Work out what type of object we've clicked on
        if(typeof(sourceObject) == "string" || (sourceObject.tagName != null && sourceObject.tagName != "INPUT")){
            this.requestType    = "get";
        } else {
            this.requestType    = "post";

            // Find form
            this.form = sourceObject.parentNode;
            while(this.form.tagName != "FORM"){
                this.form = this.form.parentNode;
            }

            // Did we find a form?
            if(this.form.tagName != "FORM"){
                alert("Unable to complete ajax request. Form was not found.");
                return;
            }
        }

        // Store generic values
        this.destinationLayer        = typeof(destinationId) == "string"?(destinationId=="self"?"self":document.getElementById(destinationId)):destinationId;
        this.sourceObject            = sourceObject;
        this.responseFunction        = responseFunction;

        // Do 'post' stuff
        if(this.requestType == "post"){
            this.createAjaxControlFrame();
            this.originalFormAction        = this.form.action;
            this.originalFormTarget        = this.form.target;
            this.form.target            = "ajaxFrame";

            // Insert a temporary postButton duplicate. This is needed because when the ajax event is attached directly to a
            // submit button it fails to include the submit button's name and value when submitting the form.
            this.ajaxTempButton            = document.createElement("input");
            this.ajaxTempButton.type    = "hidden";
            this.ajaxTempButton.name    = this.sourceObject.name;
            this.ajaxTempButton.value    = this.sourceObject.value;
            this.form.appendChild(this.ajaxTempButton);

            // Create hidden input to identifer that this form has been submitted through an ajax call
            this.createAjaxIdentifier("post");

            //Submit the form
            this.form.submit();

            //Revert form action and target to original values
            this.form.action = this.originalFormAction;
            this.form.target = this.originalFormTarget;

            //Remove temporary Button element
            if(this.ajaxTempButton){
                this.form.removeChild(this.ajaxTempButton);
            }
            return false;

        // Do 'get' stuff
        } else {

            // Show Ajax Loader
            this.startLoader();
            if(typeof(loaderFunction) == "function"){
                loaderFunction(this.loader,"loader");
            } else {
                if(this.destinationLayer){
                    this.writeToDestination(this.loader);
                }
            }

            var url = this.createAjaxIdentifier(typeof(this.sourceObject) == "string"?this.sourceObject:this.sourceObject.href);
            this.createAjaxControlFrame(url);
            return false;
        }
    }

    // Response action after the form has been submitted to the iframe
    // If not destination has been selected then do nothing.
    this.doResponse= function(){
        if(this.ajaxFrame.contentWindow.document.body){

			// Get response
		    var responseHtml = this.ajaxFrame.contentWindow.document.body.innerHTML;

            // Fix a really stupid IE bug whereby it does not copy some/all of the PARAM tags properly.
            // A big problem is the "flashvars" attribute. It seems to just blank it. Possible something to
            // do with the case being used in the original object. Anyway, this rebuilds the first object it
            // finds.
            if(Browser.Engine.trident){
                var object = this.ajaxFrame.contentWindow.document.body.getElementsByTagName("OBJECT")[0];
                if(object){
                    var params  = object.getElementsByTagName("PARAM");
                    var phtml   = "";
                    for(i in params){
                        phtml += "<param name='"+params[i].name+"' value='"+params[i].value+"' />";
                    }
                    responseHtml2 = responseHtml.replace(/\<PARAM[^\>]*?\>/ig,"");
                    var c1 = responseHtml2.split("</OBJECT>");
                    responseHtml = c1[0]+phtml+"</OBJECT>"+c1[1]+"<br />";
                }
            }
            this.ajaxFrame.contentWindow.document.body.innerHTML = "";
        }

        // Have we asked to run a different response Function?
        if(typeof(this.responseFunction) == "function"){
            this.responseFunction(responseHtml,this.destinationLayer);
        } else {
            // Should we update the destination element if it's been set?
            // If it has been set to "self" then return the value;
            // If a specific command has been returned then issue it..

            // If the content returned is requesting a location, go there!
            if(responseHtml.substr(0,9) == "location:"){
                responseHtml = responseHtml.replace("location:","");
                responseHtml = responseHtml.replace("&amp;","&");
                parent.location.href = "http://"+window.location.hostname+responseHtml;
            } else
            // Run appropriate response function
            if(this.destinationLayer){
                this.writeToDestination(responseHtml);
            }
        }

        // Run very last function and unflag as active
        this.onComplete();
    }

    // Write HTML to specificed destination
    this.writeToDestination = function(txt){
        this.destinationLayer.innerHTML = txt;
    }

    // Apply identifier to the URL so that PHP has something to work with too
    this.createAjaxIdentifier = function(url){
        if(url=="post"){
            this.ajaxIdentifier         = document.createElement("input");
            this.ajaxIdentifier.type    = "hidden";
            this.ajaxIdentifier.name    = "ajax";
            this.ajaxIdentifier.value    = new Date().getTime();
            this.form.appendChild(this.ajaxIdentifier);
        } else {
            var d = new Date();
            if(url.indexOf("?") > -1){
                url += "&ajax=1&ajaxrand="+d.getTime();
            } else {
                url += "?ajax=1&ajaxrand="+d.getTime();
            }
            return url;
        }
    }

    // Create Ajax controller iframe
    this.createAjaxControlFrame = function(url){
        if(this.debug == false || (this.debug == true && this.ajaxFrame == null)){
            this.canvasObject                        = document.createElement("div");
            this.canvasObject.style.position        = "absolute";
            this.canvasObject.style.top                = "0px";
            this.canvasObject.style.left            = "0px";
            this.canvasObject.style.backgroundColor = "#ffffff";
            this.canvasObject.style.visibility        = this.debug == true?'visible':'hidden';
            this.canvasObject.style.width            = "100px";
            this.canvasObject.style.height            = "100px";
            this.canvasObject.id                    = "canvasObjectFrame";

            if(document.addEventListener){
                this.canvasObject.innerHTML                += "<iframe id='ajaxFrame' style='display width='100' height='100' name='ajaxFrame'"+(typeof(url)!="undefined"?" src='"+url+"'":"")+"></iframe>";
                document.body.appendChild(this.canvasObject);
                this.ajaxFrame            = document.getElementById("ajaxFrame");
                this.ajaxFrame.addEventListener("load",function(){myAjax.doResponse();},false);
            } else {
                if(typeof(url) != "undefined"){
                    if(url.indexOf("about:blank")>-1){
                        url2 = window.location.href.split("?");
                        url = url.replace("about:blank",url2[0]);
                    }
                }
                this.canvasObject.innerHTML    += "<iframe id='ajaxFrame' name='ajaxFrame' width='100' height='100'"+(typeof(url)!="undefined"?" src='"+url+"'":"")+" onload='myAjax.doResponse();'></iframe>";
                document.body.appendChild(this.canvasObject);
                this.ajaxFrame    = document.getElementById("ajaxFrame");
            }
        }

        // Return false if 'get'
        if(this.requestType == "get"){
            return false;
        }
    }

    // Remove Ajax controller iframe
    // We remove it after the call to stop the browser's back button getting confused and going back through
    // pages of the iframe.
    this.removeAjaxControlFrame = function(){
        if(myAjax.ajaxFrame){
            myAjax.canvasObject.parentNode.removeChild(myAjax.canvasObject);
            myAjax.ajaxFrame = null;
        }
    }

    // Create Loading bar
    this.startLoader = function(){
        if(typeof(this.loader) == "undefined"){
            this.loader = "<span style=\"display:block;\"><span style=\"font-size:1px;display:block;width:120px;height:10px;background-image:url('"+myEnv.imgPath+"/ajax_loader_bg.gif');\">&nbsp;</span></span>";
        }
    }
}

// Screen Brightness Control
var myScreenBrightness = new function(showLoader){
    this.layers= new Array();

    // Darken screen
    this.darken    = function(showLoader){

        // Check for windowHeight fix.
        var winScrollHeight = myEnv.fixWindowScrollHeight();

        var ds_id = this.layers.length+1;
        var ds = new Element('div', {
            'styles': {
                'background-color' : '#000000',
                'opacity' : 0.8,
                'top' : 0+"px",
                'left' : 0+"px",
                'position': 'absolute',
                'height' : winScrollHeight+"px",
                'width' : window.getScrollWidth()+"px",
                'z-index':500+myPopup.layers.length+ds_id,
                'visibility' : 'hidden'
            }
        });

        // Create Loader?
        if(showLoader === true){
            ds.setStyles({
                "background-image"        : "url("+myEnv.get("imgPath")+"/ajax_loader_bg.gif')",
                "background-repeat"        : "no-repeat",
                "background-position"    : ((window.getWidth()/2)-30)+window.getScrollLeft()+"px "+(window.getScrollTop()+(window.getHeight()/2)-15)+"px"
            });
        }

        ds.setProperty("id","darkenScreen"+ds_id);
        ds.inject(document.body);
        ds.setStyle("visibility","visible");

        // Add Darkened Screen layer to history
        this.layers.push("darkenScreen"+ds_id);
    }

    // Undarken screen
    this.undarken = function(){
        var id = this.layers.pop();
        if($(id)){
            $(id).empty();
            $(id).dispose();
        }
    }
}


/* CREATE POPUP WINDOWS THAT CONTAIN DYNAMIC CONTENT */
var myPopup = new function(){
    this.layers     = new Array();
    this.objects    = new Object();

    this.getMostRecentObject = function(){
        id = this.layers[this.layers.length-1];
        return this.objects[id];
    }

    this.open = function(content,popupClassName,showCloseButton,responseFunction){

        // Create Unique Identifier
        var uniqueId = Math.ceil(Math.random()*6000);
        this.layers.push(uniqueId);
        this.objects[uniqueId]      = new Object();
        this.objects[uniqueId].id   = uniqueId;
        o = this.objects[uniqueId];

        o.responseFunction  = responseFunction;
        o.showClose         = typeof(showCloseButton)=="boolean"?showCloseButton:true;
        o.popupClassName    = "popupBox_"+(popupClassName == null||popupClassName==""?"frame800":popupClassName);
        if(o.showClose === true){
            o.alertContent  = "<div id='popupClose"+uniqueId+"' class='popupClose'><a href='Javascript:void()' onclick='myPopup.close()'><img src='"+myEnv.get("imgPath")+"/popup_close.png' width='32' height='32' alt='Close Window' title='Close' /></a></div>";
        } else {
            o.alertContent      = "";
        }

        // Darken Screen
        myScreenBrightness.darken();

        // Create main element
        o.popupBox = new Element('div', {
            'styles': {
                'visibility' : 'hidden',
                'position': 'absolute',
                'top':0+"px",
                'left':0+"px",
                'z-index'    : 500+(this.layers.length+myScreenBrightness.layers.length)
            },
            "id" : ("popupBox"+uniqueId),
            "class" : o.popupClassName+" popupBoxGlobal"
        });

        // Inject onto page
        o.popupBox.injectInside(document.body);

        // Set standard box HTML
        o.popupBox.set("html",
                "<div id='popupBoxInner"+uniqueId+"' class='popupInner'>"
            +    "<div id='popupBoxContentArea"+uniqueId+"' class='popupContent'></div>"
            +    "<div style='clear:both;height:1px;font-size:1px'>&nbsp;</div>"
            +    "</div>"
            +    "<div class='popupBottomBar' style='clear:both'>"+o.alertContent+"</div>"
        );

        // Store close button
        o.closeButton = $("popupClose"+uniqueId);

        o.popupBox          = $("popupBox"+uniqueId);
        o.popupBoxContent   = $("popupBoxContentArea"+uniqueId);
        o.popupBoxInner     = $("popupBoxInner"+uniqueId);
        o.popupWidth        = o.popupBox.getStyle("width").toInt();
        o.emptyHeight       = o.popupBox.getCoordinates().height;
        o.contentBg         = o.popupBoxContent.getStyle("background-color");
        o.contentFg         = o.popupBoxContent.getStyle("color");
        o.contentPad        = o.popupBoxContent.getStyle("padding");
        delete o;
        this.fetchContent(content,false);
    }

    // Update content of currently active popup
    this.update = function(content){
        obj = this.getMostRecentObject();
        obj.popupBox.setStyle("height","auto");
        obj.popupBoxInner.setStyle("height","auto");
        this.fetchContent(content,true);
    }

    // Prepare show function
    this.showContent = function(content,isLoader){
        obj = myPopup.getMostRecentObject();

        // Write imported content first?
        if(typeof(content) == "string"){

            // Update content if it's a direct link to an image
            content = myPopup.updateIfJustImage(content);
            obj.popupBoxContent.setStyle("height","auto");
            obj.popupBoxContent.set("html",content+"<br />");
        }

        // Calculate new size
        var newInner = myPopup.calculateNewSize(isLoader);

        // Prepare close button
        if(isLoader != "loader"){
            if(typeof(obj.responseFunction) != "undefined"){
                obj.responseFunction();
            }
        }
    }

    this.showUpdatedContent = function(content,isLoader){
        obj = myPopup.getMostRecentObject();

        // Write imported content first?
        if(typeof(content) == "string"){

            // Update content if it's a direct link to an image
            content = myPopup.updateIfJustImage(content);

            // If the content returned is requesting a location, go there!
            if(content.substr(0,9) == "location:"){
                content = content.replace("location:","");
                if(content.substr(0,5) == "close"){
                    myPopup.close();
                } else {
                    content = content.replace("&amp;","&");
                    parent.location.href = "http://"+window.location.host+content;
                }
            } else {
                obj.popupBoxContent.setStyle("height","auto");
                obj.popupBoxContent.set("html",content+"<br />");
            }
        }

       // Calculate new size
        var newInner = myPopup.calculateNewSize(isLoader);

        // Run response function?
        if(typeof(obj.responseFunction) != "undefined"){
            obj.responseFunction();
        }
    }

    // Fetch content and show
    this.fetchContent = function(content,isUpdate){
        obj = myPopup.getMostRecentObject();

        // Get Content
        if(typeof(content) == "object"){

            // Are we getting content from an ajax call using the link on the A tag?
            if(content.tagName == "A"){

                // Update the link so that it contains a flag to highlight the fact that this url is being called
                // via the ajax popup method.
                content.href = content.href.replace("&ajaxpopup=1","");
                content.href = content.href.replace("?ajaxpopup=1","");
                if(content.href.indexOf("?") > -1){
                    content.href += "&ajaxpopup=1";
                } else {
                    content.href += "?ajaxpopup=1";
                }

                myAjax.doRequest(content.href,this.popupBoxContent,(isUpdate?this.showUpdatedContent:this.showContent),(isUpdate?this.showUpdatedcontent:this.showContent));
            } else {
                // Must be getting content from inside an existing element so get its innerHTML
                $("popupBoxContentArea"+obj.id).innerHTML = content.innerHTML;
                if(isUpdate){
                    this.showUpdatedContent();
                } else {
                    this.showContent();
                }
            }
        } else
        if(content.charAt(0) == "/"){
            // Append the host to the relative path
            // Obviously, relative paths only work on the domain we're on because you can't
            // grab content from different domains.
            content = "http://"+window.location.host+content;
            myAjax.doRequest(content,this.popupBoxContent,(isUpdate?this.showUpdatedContent:this.showContent),(isUpdate?this.showUpdatedcontent:this.showContent));
        } else {
            // Normal insert
            $("popupBoxContentArea"+obj.id).innerHTML = content;
            if(isUpdate){
                this.showUpdatedcontent();
            } else {
                this.showContent();
            }
        }
    }.bind(this)

    this.updateIfJustImage = function(content){
        if(content.substr(0,5).toLowerCase() == "<img "){
            var geturl = new RegExp(/src="([^ ]+)/i);
            var url = geturl.exec(content)[1];
            if(content.indexOf("?") > -1){
                url2 = url.split("?");
                url = url2[0];
            }
            var file = url.split("/");
            filename = file.pop();
            content = "<div style='text-align:center;height:500px;overflow:auto;'><img src='"+url+"' style='margin-left:auto;margin-right:auto' /><br /><p class='smalltext'>Name: "+filename+"</p></div>";
        }
        return content;
    }

    this.calculateNewSize = function(isLoader){

        obj = myPopup.getMostRecentObject();

        // Default height
        var boxHeight    = obj.popupBox.getSize().y;
        var newInner   = false;

        // Don't worry about this for load because the loader isn't doing anything drastic
        // to the height anyway!!
        if(isLoader != "loader"){

            if((boxHeight + 50) > window.getHeight()){
                newInner = true;
                boxHeight = window.getHeight()-100;
                obj.popupBox.setStyle("height",boxHeight+"px");
            }

            // Opera and > IE 7 don't like overflow
            if(myEnv.browserIE6){
                myPopup.overflowFix(boxHeight);
            } else {
                if(newInner === true){
                    obj.popupBoxInner.setStyle("height",(boxHeight-obj.emptyHeight)+"px");
                    obj.popupBoxInner.setStyle("overflow","auto");
                }
            }
        }

        var startTop    = window.getScrollTop()+((window.getHeight() - boxHeight) / 2);
        var startLeft    = (window.getWidth() - obj.popupWidth) / 2;

        // Re-position the popup box
        obj.popupBox.setStyles({
            "visibility"    : "visible",
            "top"            : (startTop)+"px",
            "left"            : startLeft+"px"
        });

        return newInner;
    }

    // Close last opened popup
    this.close = function(obj){
        obj = myPopup.getMostRecentObject();

        if(obj.showClose === true){
            $("popupClose"+obj.id).dispose();
        }

        myPopup.layers.pop();

        // This might not exist if the popup used an iframe (< IE 7) to get content
        if($("popupBoxContentArea"+obj.id)){
            $("popupBoxContentArea"+obj.id).empty();
            $("popupBoxContentArea"+obj.id).dispose();
            $("popupBoxInner"+obj.id).empty();
            $("popupBoxInner"+obj.id).dispose();
        }
        $("popupBox"+obj.id).empty();
        $("popupBox"+obj.id).dispose();
        myScreenBrightness.undarken();
        return true;
    }

    // Create iFrame for Opera and < IE7 to replicate "overflow:auto" command
    this.overflowFix = function(boxHeight){
        obj = myPopup.getMostRecentObject();

        var operaFrame = new Element('iframe', {
            'styles': {
                'width'        : "100%",
                'height'    : (boxHeight-obj.emptyHeight)+"px",
                'display'    : "none",
                'border'    : "none"
            },
            'frameborder'    : 0
        });
        var innerContent = obj.popupBoxContent.innerHTML;
        obj.popupBoxInner.innerHTML = "";

        obj.popupBoxInner.setStyle("padding","0px");
        operaFrame.injectInside(obj.popupBoxInner);
        if(operaFrame.contentDocument){
             doc = operaFrame.contentDocument; // For NS6
        }else if(operaFrame.contentWindow){
            doc = operaFrame.contentWindow.document; // For IE5.5 and IE6
        }
        var sSheets="";
        for(var i=0;i<document.styleSheets.length;i++){
            sSheets += "<link rel='stylesheet' type='text/css' href='"+document.styleSheets[i].href+"' /></head>";
        }
        doc.open();
        doc.write(myEnv.docType+"<head>"+sSheets+"</head><body style='margin:0px;padding:"+obj.contentPad+";width:90%;background-image:none;color:"+obj.contentFg+";background-color:"+obj.contentBg+"'>"+innerContent+"</body></html>");
        doc.close();
        operaFrame.setStyle("display","block");
    }
}
