$(document).ajaxError(function(e, xhr, settings) {
    mainJs.inProgress = 0;  // Reset block switch for further ajax calls!

    try {
        var message = 'An error occured while calling '+settings.url+ ((settings.data && settings.data.length > 0)?' with params : '+settings.data:'');
        console.log('$(document).ajaxError',message, e, settings);
    }catch(e){}

    mainJs.hideLoader(); // Hide the loader
    return false; //so event bubbling is stopped. http://www.switchonthecode.com/tutorials/javascript-working-with-events
});

var VisitorControllers = new Array('myphotos','myvideos','me','myfriends'); // These controller will have the user id appended to the URL

var mainJs = {
    // Variable to hold data required to pass-on to pageLoadComplete when AJAX page load call completes successfully [see loadPage]
    loadPageData : null,

    // If true a page load is in progress
    inProgress : 0,

    //The XHR object used for page load. This object will be used to abort running requests.
    pageLoadXHR : null,

    //This variable indicates that the loadPage() has been called. This variable will be used only by loadPage() and the callback for the $.history plugin.
    //@important : Don't mess with it. The variable will be null indicating the initial state, if not it will comprise a bool
    loadPageInvoked : null,

    // This function blocks the UI while page is being loaded via AJAX
    // Dependency: PageConfig.msgLoading
    showLoader : function () {
        $('#main').block({message: PageConfig.msgLoading});
    },

    // This function un-blocks the UI while page is being loaded via AJAX
    hideLoader : function() {
        $('#main').unblock();
    },

    // This function shortens the url suffixed to #
    trimUrl : function (url, args) {
        if( !url || url == undefined || url == null ) return '';

        // Removing known prefix from url (if available)
        var i = 0;var p = '';
        if( url.startsWith( urlDefCtlrFx ) ) {i = urlDefCtlrFx.length - 1;p = 'f';}
        else if( url.startsWith( urlDefCtlr ) ) {i = urlDefCtlr.length - 1;p = 'd';}
        else if( url.startsWith( urlAppRoot ) ) {i = urlAppRoot.length - 1;p = 'r';}

        // adding user id if not available
        if( i > 0 ) {
            var id = url.match(/id:(\d+)/i);
            if( (!id || id.length < 1) && VisitorControllers.in_array(Controller) >= 0 ) {
                var obj = mainJs.getCtrlMethd(url);
                // Waseem: Commented out code was padding controller's method when found in the 'url', however, it's already part of 'url' and removing it might break url, hence, short-circuit if was modified
                // url = url + ( url.endsWith('/') ? '' : '/' ) + ( (obj.mthd)?obj.mthd:"start" ) + '/id:' + Me.id + '/'; //Added start before ID.
                url = url + ( url.endsWith('/') ? '' : '/' ) + ( (obj.mthd)?"":"start/" ) + 'id:' + Me.id + '/'; //Added start before ID.
            }
        }

        return p+url.substr(i);
    },

    // This function is anti-trim i.e. it expands and resolves shortened url into valid page url
    expandUrl : function (fullUrl) {
        var newUrl = '';
        var i = fullUrl.indexOf('#');
        if( i != -1 ) {
            var p = fullUrl.substr(i+1);
            if( p ) {
                switch( p.substr(0,1) ) { //ideally p[0] should be enoug, but it doesnt work in IE7
                    case 'f':
                        newUrl = urlDefCtlrFx + p.substr(2);
                        break;
                    case 'd':
                        newUrl = urlDefCtlr + p.substr(2);
                        break;
                    case 'r':
                        newUrl = urlAppRoot + p.substr(2);
                        break;
                    default:
                        newUrl = p.substr(2);
                        break;
                }
            //console.log(p, newUrl);
            }
        }

        return newUrl;
    },

    // This fx extracts controller and method (if any) from the given URL
    getCtrlMethd : function(url) {
        if(url.length < 1) return {ctrl:"", mthd:""}

        var cm = url;
        var l  = urlDefCtlr.length;
        cm = (cm.substr(0,l) == urlDefCtlr)? cm.substr(l) : cm;
        var splt = cm.split('/');
        var ctrl = splt[0];
        var mthd = splt[1];

        if(mthd != undefined){
            var t = mthd.match(/^([a-zA-Z]+:{0})$/i);
            mthd = (t != null)?t[1]:'';
        }

        return {ctrl:ctrl, mthd:mthd}
    },

    //Dependency : urlDefCtlr
    fetchURLPageData : function( url ){
        if(!url || !url.trim || (url.trim()).length < 1) return false;
        url	= url.trim();
        var pre = url.substring("http://".length);
        url	= "http://" + pre.replace('//','/');

        var furl = ( (ind = url.indexOf('#')) > 0)? url.substr(0,ind):url;
        var lurl = mainJs.expandUrl(url);
        var rez	 = mainJs.getCtrlMethd(furl);
        var rez1 = mainJs.getCtrlMethd(lurl);

        var getParams = function(url, ctrl, mthd){
            var l = ctrl+'/'+mthd;
            var nprms = url.substr(url.indexOf(l)+l.length+1);
            nprms = nprms.split('/');
            var temp = [];
            for(var i=0; i < nprms.length; i++){
                if(nprms[i].length && nprms[i].length > 0) temp[i] = nprms[i];
            }
            return temp;
        }

        var nprms = getParams(lurl, rez1.ctrl, rez1.mthd);
        var oprms = getParams(furl, rez.ctrl, rez.mthd);

        return {
            nurl:lurl,
            ncontroller: rez1.ctrl,
            nmethod: rez1.mthd,
            nparams: nprms,
            ourl:furl,
            ocontroller: rez.ctrl,
            omethod: rez.mthd,
            oparams: oprms
        };//namespace:namespace
    },

    fetchPageData : function(){
        return this.fetchURLPageData(document.location.href);
    },

    formatUrl : function(oldUrl, url) {
        if( !oldUrl || oldUrl == undefined || oldUrl == null ) return '';
        if( !url || url == undefined || url == null ) return oldUrl;

        /* Waseem: Following code was commented out since modifying original url (oldUrl variable) will result in page reload !!!
        // Strip out old 'id' argument since user may have moved to another user profile. Latest id component is in 'url'
        var id = oldUrl.match(/id:\d+\/?/i);
        if( id && id.length > 0 ) {
            oldUrl = oldUrl.replace(id[0],"");
            //console.log("After: ", oldUrl);
        }

        // Removing theme selection info from URL to avoid clutter
        var themeInfo = oldUrl.match(/theme\/t:\w+\/?(sa:\d)?\/?/ig);
        if( themeInfo && themeInfo.length > 0 ) {
            oldUrl = oldUrl.replace(themeInfo[0],"");
            //console.log("After: ", oldUrl);
        }
*/

        return oldUrl + '#' + url;
    },

    pageLoadSuccess: function(data, textStatus, optArgsObj) {
                
        //Resolving the optional arguments "optArgsObj" with the default values
        optArgsObj = jQuery.extend({appendHashComp : true}, optArgsObj || {});

        mainJs.inProgress = 0;  // Reset block switch for further ajax calls!
        // if(console.log) console.log( 'Call to url "%s" completed with status "%s"', mainJs.loadPageData.lastUrl, textStatus);

        if(!data || (data.trim()).length < 1 ) {
            mainJs.hideLoader();
            //document.location.href = urlDefCtlr; //Empty page returned. Redirect to home page.
            return; //$(document).trigger('PAGE_EMPTY');
        }

        data = data.trim();

        //The following code adjusts the IE7 emulation mode based on the page
        $('meta[http-equiv=X-UA-Compatible]').remove();
        var pt = data.match('<meta http-equiv=\"X\-UA\-Compatible\".* \/>');
        if(pt != null && pt.length >= 0) $('head').append(pt[0]);

        // Start-of: Replacing attributes of existing 'body' element with received DOM
        var res = data.match(/\<body/i);
        if(res && res.length > 0) {
            // First, removing existing attributes ...
            var bodyDom = $('body').get(0);
            if( bodyDom.clearAttributes ) bodyDom.clearAttributes(); //clearAttributes exists in IE
            else {
                while( bodyDom.attributes.length ) bodyDom.removeAttribute( bodyDom.attributes[0].name );
            }

            // Pulling out attributes part from <body> declaration from received DOM
            var rawAttrz = data.match(/\<body (.*)?\>/i);
            if( rawAttrz && rawAttrz.length > 1 ) {
                rawAttrz = rawAttrz[1];
                var splittedAttrz = rawAttrz.match(/(\b\w+\b\s?)+/gi);
                for(i=0; i<splittedAttrz.length; i+=2){
                    $(bodyDom).attr(splittedAttrz[i], splittedAttrz[i+1]);
                    if(splittedAttrz[i] == 'id' && splittedAttrz[i+1] == 'home') document.location.href = urlDefCtlr; //Check if this is home page. Then redirect to home page.
                }
                delete(splittedAttrz);
            }
            delete(rawAttrz);
            delete(bodyDom);/**/
        }
        // End-of: Replacing attributes of 'body'

        var ite = new Array('#myWorldNav'/*,'.jokeWrapper','#translationBar'*/); //#main is handled separately
        var t =null;
        for(var i=0; i < ite.length; i++){
            t = $(ite[i],data);
            if(t.length > 0)$(ite[i]).html(t.html());
        }

        var o = '<div id="main">';  // NOTE: This line was grabbed from header.tpl indicating start of div#main - DON'T DARE TO TOUCH IT!
        var s = data.indexOf(o);
        var e = data.lastIndexOf('</div><!-- #main -->');  // NOTE: This line was grabbed from footer.tpl indicating end of div#main - DON'T DARE TO TOUCH IT!
        $('#main').html( data.substring(s+o.length,e).trim() );
        
        // Add the current URL as a # to the first loaded one.
        var curl = document.location.href;
        var iCurl = curl.indexOf('#');
        if( iCurl != -1 ) curl = curl.substr(0, iCurl);

        /*
         * In certain requests it is not desirable to append the hash component and therefore the
         * paramete optArgsObj.appendHashComp is used to control this behavior. For an instance when the history button is clicked
         * and the next page is "me" or any of the other controllers which need the user id appended to the url is called
         * the change in the hash triggers a call to the history callback triggering another page load
         **/
        var hashedUrlComp = null;
        if(optArgsObj.appendHashComp == true) {
            hashedUrlComp = mainJs.trimUrl( mainJs.loadPageData.lastUrl);
            document.location = mainJs.formatUrl(curl, hashedUrlComp);
        }
        /*try{ console.log('pageLoadSuccess history',document.location)}catch(e){}*/

        var json = mainJs.fetchPageData();
        json.controller = json.ncontroller;
        json.method = json.nmethod;

        $(document).trigger(mainJs.loadPageData.events.load, json);

        mainJs.bindDynamicMenus();
        mainJs.hideLoader(); // Un-block UI

        // Updating Page-Stats (for Debugging purposes)
        o = "<div id='pgExeStats'>";
        s = data.indexOf(o);
        if(s == -1) return; // Debugging info unavailable!
        e = data.lastIndexOf('</div><!--ReqStats-->');  // NOTE: This line was grabbed from footer.tpl indicating end of div#main - DON'T DARE TOUCH IT!
        var fReq = $("#pgExeStats ul li:first span").html() + ", *";
        $('#pgExeStats').html( data.substring(s+o.length,e).trim() );
        $("#pgExeStats ul li:first span").prepend(fReq);
    },

    bindDynamicMenus : function(){
        $('#myWorldNav a,#moduleMenu a, #pageRep a').bind('click',function(){
            loadPage($(this).attr('href'))
            return false;
        });
    },

    //Set an object with required parameters and call this within the closures. Use thiscarefully as
    //the chances for overriding are
    optionalArgsContainer : {},
    setOptionalArgs : function(optArgs, key) {

        //If either parameters are missing do not store!
        if(optArgs == null || key == null || !isString(key)) return false;

        mainJs.optionalArgsContainer[key] = optArgs
    },
    getOptionalArgs : function(key) {
        return mainJs.optionalArgsContainer[key];
    }
}

function loadPage(url, ajax_opts, full_page, optArgsObj) {

    var evts = new Object();
    evts.unload = 'PAGE_UNLOAD';
    evts.load	= 'PAGE_LOADED';

    mainJs.showLoader();// Block UI

    var prepUnloadData = function(){
        //Return a 'controller' and 'method' variable that gives the current controller and method.
        var json = mainJs.fetchPageData();
        if(json.ncontroller.length < 1){
            json.controller = json.ocontroller;
            json.method     = json.omethod;
        }else{
            json.controller = json.ncontroller;
            json.method     = json.nmethod;
        }

        return json;
    }

    $('#content').trigger(evts.unload, prepUnloadData() );// PAGE_UNLOAD will bubble up from #content to document

    if( mainJs.inProgress && mainJs.pageLoadXHR )
        mainJs.pageLoadXHR.abort();

    // Storing last accessed URL!
    mainJs.loadPageData = {
        lastUrl : url,
        events : evts
    };
    mainJs.inProgress = 1;
    mainJs.loadPageInvoked = true;

    if(optArgsObj) mainJs.setOptionalArgs(optArgsObj, 'hist_but_sup_ifti');
    
    	var opts = {type : 'get'
        , dataType : 'html'
        , url : url
        , success : function(data, textStatus){
            var optArgsObj = mainJs.getOptionalArgs('hist_but_sup_ifti');
            mainJs.pageLoadSuccess(data, textStatus, optArgsObj);
        }
        , timeout : 15000 // 15-secs(value in milli-seconds)
    }

    if(ajax_opts != undefined) opts = $.extend(opts, ajax_opts);
    mainJs.pageLoadXHR = $.ajax(opts);
}

$(document).ready(function(evt){
    
    var data  = mainJs.fetchPageData();

    /*$.prototype.unbind = function(type,fn){
            if(!console) return true;

            $(this).each(function(i){
                    console.group(this)
                    console.log($(this).get(0).nodeName,$(this).attr('class'),type);
                    console.groupEnd();
            })

            if(console) console.log($(this),$('#friendsListing > li a'),type);
    }*/

        
    $.history.init(function(hash){
        if(window.console) {
            console.log('$.history.init : ', hash);
            console.log('mainJs.loadPageInvoked : ', mainJs.loadPageInvoked);
            console.log('current web url : ', location.href);
        }

        if(mainJs.loadPageInvoked == false) {
            var url = optArgsObj = null;
            if(hash.length > 0) {
                //Remove 'd' from hash
                var xHash = hash.replace(/^d\//ig, '');//Cannot use substring
                url = urlDefCtlr + xHash;
            } else {
                url = location.href;
                url = url.replace(/#.*/ig, '');
                optArgsObj = {
                    appendHashComp : false
                }
            }

            if(window.console) console.log("Page to load for history : ", url);
            loadPage(url, null, null, optArgsObj);
        }
        mainJs.loadPageInvoked = false;
    });/**/

    var isParamsSame = function(nparams, oparams){
        if(nparams.length != oparams.length) return false;
        var found = false;

        for(var x in nparams){
            found = false;
            for(var y in oparams){
                if(nparams[x] == oparams[y]) found = true;
                break;
            }
            if(!found) return false;
        }

        return true;
    }

    //Ifti : Moved this snippet from underneath mainJs.bindDynamicMenus(); statement as when the page is refreshed with a url
    //comprising of #, the logo does not get bound.
    try{
        if(window.Controller && Me.id > 0){
            //This is a static menu, should be bound only once.
            $('#mainNav a, #branding a').bind('click',function(){
                loadPage($(this).attr('href'))
                return false;
            });
        }
    }catch(e){}

    if(data.nurl.length > 0 &&
        (data.ncontroller != data.ocontroller || data.nmethod != data.omethod )){

        if(data.ncontroller == data.ocontroller){	//Check the methods
            var alias	= new Array("","start");	//Check if both the methods are essentially pointing to the same page
            var t1 = alias.in_array(data.nmethod);	//Like PHP, returns -1 if not found.
            var t2 = alias.in_array(data.omethod);
            //try{console.log(data,data.nmethod,data.omethod,t1,t2,t1+t2)}catch(e){}
            if( t1 == -1 || t2 == -1 || !isParamsSame(data.nparams, data.oparams) ) loadPage(data.nurl);
        }
        else
            loadPage(data.nurl) //If controllers are different, load the page

        return true; // Don't process current page any-more (we have loaded another page specified after # in url)
    }

    if(data.ncontroller == data.ocontroller && data.nmethod == data.omethod && !isParamsSame(data.nparams, data.oparams)) //In case the both the URLs point to the Me page, they can have same methods, but they may be pointing to different profiles.
        loadPage(data.nurl);

    mainJs.bindDynamicMenus();   

});