/*
 * includer.js
 * $Revision: 1.20 $
 *
 * dependencies: jQuery
 *
 * (c) 1992-2009 Cisco Systems, Inc. All rights reserved.
 * Terms and Conditions: http://cisco.com/en/US/swassets/sw293/sitewide_important_notices.html
 */
var host = location.host;
if (typeof(cdc) == "undefined") cdc = {};
if (typeof(cdc.includer) == "undefined"){
	cdc.includer = {};
	if (typeof(cdc.includer.alreadyInPage) == 'undefined'){
		cdc.includer.alreadyInPage = [];
	}

/*
Property: cdc.includer.domainConfig

Description:
- Adding subdomain main array object in to cdc.includer.domainConfig. By default this array object contains 4 subdomains. 
- Array Structure ['newsroom', 'tools', 'about',  'investor'].

*/
	
	cdc.includer.domainConfig = {
		subdomains:['newsroom', 'tools', 'about',  'investor']
	};

/*
Method: cdc.includer.addSubDomain()

Description:
-	addSubDomain() works with one param and this param could be string type or array type. It appends the subdomain in main array object of cdc.includer.domainConfig.subdomains.

Sample usages:
>	cdc.includer.addSubDomain('products');
>	cdc.includer.addSubDomain(['groups', 'services', 'products']);

Param:
-	This function using only one param called 'o'. This param contains the one array/string type of parameter to add the subdomains. 

*/

	cdc.includer.addSubDomain = function(o){
		if (typeof o == "string") {
			o = [o];
		}

		if(o.length) {
			for(i in o){
				if(cdc.includer.domainConfig.subdomains.join().indexOf(''+o[i]) < 0) {
					cdc.includer.domainConfig.subdomains.push(o[i]);
				}
			}
		}		
	}	

/*
Method: cdc.includer.removeSubDomain()

Description:
-	removeSubDomain() works with one param and this param could be string type or array type. It appends/removes the subdomain in main array object of cdc.includer.domainConfig.subdomains.

Sample usages:
>	cdc.includer.removeSubDomain('tools');
>	cdc.includer.removeSubDomain(['tools', 'products', 'services']);

Param:
-	This function using only one param called 'o'. This param contains the one array/string type of parameter for remove the subdomains. 

*/
	
	cdc.includer.removeSubDomain = function(o){
		if (typeof o == "string") {
			o = [o];
		}

		if(o.length) {
			for(i in o){
				if(cdc.includer.domainConfig.subdomains.join().indexOf(''+o[i]) > 0) {
					arrString = cdc.includer.domainConfig.subdomains.join('~');
					arrString = arrString.split('~');
					cdc.includer.domainConfig.subdomains = [];
					for(x in arrString){
						if(arrString[x] != o[i]){
							cdc.includer.domainConfig.subdomains.push(arrString[x]);
						}
					}
				}
			}
		}
	}

	
/*
Object : cdc.includer.widget{}

Description:
- This object contains the list of assets which we need to include on page.

*/	
	cdc.includer.widgets = {
		'module-sbt':{
			js: [
				'http://cisco.com/cdc_content_elements/visualsciences/visualsciences.js',
				'http://cisco.com/web/fw/j/sbt.js'
			],
			css: ['http://cisco.com/web/fw/c/sbt.css']
		},
                'widget-popular':{
			js: [
				'/web/fw/w/widget-popular.js',
				'http://cmsg-ws.cisco.com/js/discovery.js'
			]
		},
		'cdc-widget-accordion' : {
			js: [
				'http://www.cisco.com/cdc_content_elements/visualsciences/visualsciences.js',
				'/web/fw/lib/jquery.hoverIntent.minified.js',
				'/web/fw/w/accordion/widget-accordion.js'
			]
		},
		'cdc-widget-lightbox' : {
			js: [
			  '/web/fw/lib/jqmodal.js',
			  '/web/fw/lib/jquery.bgiframe.min.js',
			  'http://www.cisco.com/cdc_content_elements/flash/swfobject/swfobject.js',
			  '/web/fw/w/lightbox/lightbox.js'
			],
			css: [
			   '/web/fw/w/lightbox/lightbox.css'
			]
		},

		// Note: Component Library code is now in /web/fw/w/cl/cl.js
		'_default':{
			js: [
				//'/web/fw/w/cl/cl.min.js'
				'/web/fw/w/cl/cl.js'
			]
		}
	};


/*
Method: cdc.includer.search()

Description:
- This function based on one object parameter <cdc.includer.widgets>. It reads the _default property of widget object to load CSS file in to DOM.

*/	
	cdc.includer.search = function(widgets){
		for (id in widgets){
			if (id == '_default' || document.getElementById(id)){
				if (widgets[id]['css'] && widgets[id]['css'].length){
					cdc.includer.loadCss(widgets[id]['css']);
				}
				if (widgets[id]['js'] && widgets[id]['js'].length){
					cdc.includer.loadJs(widgets[id]['js'],
						{callback:widgets[id]['callback']}
					);
				}
				else if (widgets[id]['callback']){
					(widgets[id]['callback'])();
				}
			}
		}
	};


/*
Method: cdc.includer.uniquifyIncludes()

Description:
- 

*/
	cdc.includer.uniquifyIncludes = function(includes,type) {
		var dedup = {};
		var deduped = [];
		var nodeName, attrName;
                if (type == 'js') {
			nodeName = 'script';
			attrName = 'src';
		}
		else if (type == 'css') {
			nodeName = 'link';
			attrName = 'href';
		}

		for (var i=0;i<includes.length;i++){
			dedup[includes[i]]=1;
		}
		if (typeof(cdc.includer.alreadyInPage) != 'undefined'){
			for (var i=0;i<cdc.includer.alreadyInPage.length;i++){
				dedup[cdc.includer.alreadyInPage[i]]=0;
			}
		}
		jQuery(nodeName).each(function(){
			if (this[attrName]){
				var uncachedUrl = this[attrName].replace(/http:\/\/[^\/]*/,'');
				uncachedUrl = uncachedUrl.replace(/[\&\?]cacheReset=[0-9\-]*/,'');
				dedup[uncachedUrl]=0;
			}
		});
		for (var i=0;i<includes.length;i++){
			if (dedup[includes[i]]){
				deduped.push(includes[i]);
			}
		}
		return deduped;
	};

	
/*
Method: cdc.includer.loadCss()

Description:
- - This function has two parameters. includes parameter stores the loaction of CSS assets. This function checks DOM for CSS if CSS is alredy loaded then it wont load the CSS otherwise it load the CSS file into head section of HTML page through DOM.

*/	
	cdc.includer.loadCss = function(includes,extraArgs){
		if (typeof includes == "string") {
			includes = [ includes ];
		}
		if (!extraArgs){
			extraArgs = {};
		}

		includes = cdc.includer.uniquifyIncludes(includes,'css');
		for (var i=0;i<includes.length;i++){
			//NEED TO check for css in dom
			//include css if not there already
			var css = document.createElement('link');
			css.setAttribute('rel', 'stylesheet');
			css.setAttribute('type', 'text/css');
			css.setAttribute('href', includes[i]);
                        if (extraArgs.ids && extraArgs.ids[i]) {
				css.setAttribute('id', extraArgs.ids[i]);
                        }
			document.getElementsByTagName('head')[0].appendChild(css);
			cdc.debug.log("appended the stylesheet %o to the HEAD", includes[i]);
		}

	};

/*
Method: cdc.includer.Js()

Description:
-  This function has two parameters. includes parameter stores the loaction of JS assets. This function checks DOM for JS if JS file is alredy loaded then it won't load the JS otherwise it load the JS file into head section of HTML page through DOM.

*/
	cdc.includer.loadJs = function(includes,extraArgs){
		cdc.debug.log('includer: loadjs');
		cdc.debug.log('includer: includes is a '+typeof includes);
		if (typeof includes == "string") {
			includes = [ includes ];
		}
		else {
			cdc.debug.log('includer: it is '+includes.length+' long.');
			cdc.debug.log('includer: first element: '+includes[0]);
		}

		if (!extraArgs){
			extraArgs = {};
		}

		if (!extraArgs.hasBeenCleaned){
			includes = cdc.includer.uniquifyIncludes(includes,'js');
			extraArgs.hasBeenCleaned=1;
			if (includes.length==0){
				if (extraArgs.callback){
					cdc.debug.log('includer: there are no js files and there is a callback, doing it.');
					extraArgs.callback();
				}
				return;
			}
		}

		var currentFile = includes.shift();
		//cdc.debug.log('includer: currentFile is '+currentFile);
		var scriptNode = document.createElement('script');
		document.getElementsByTagName("head")[0].appendChild(scriptNode);
		scriptNode.language='javascript';
		if (extraArgs.ids && extraArgs.ids.length) {
			scriptNode.id = extraArgs.ids.shift();
		}

		if (includes.length){
			cdc.debug.log('includer: there are more includes after this one so build in recursion using an event handler on the script node');
			if(document.attachEvent){//IE
				scriptNode.onreadystatechange = function(){
					if (this.readyState == "loaded") {
						cdc.includer.loadJs(includes,extraArgs);
					}
				}
			}
			else{
				scriptNode.onload = function(){cdc.includer.loadJs(includes,extraArgs);};
			}
		}
		else if (extraArgs.callback){
			cdc.debug.log('includer: there are no more includes after this one but there is a callback so put it on the script node as a handler');
			if(document.attachEvent){//IE
				scriptNode.onreadystatechange = function(){
					if (this.readyState == "loaded") {
						extraArgs.callback();
					}
				}
			}
			else{
				scriptNode.onload = function(){extraArgs.callback();};
			}
		}
		var src = currentFile;
		if (jQuery.browser.msie && !src.match(/noCacheBust/) && !extraArgs.noCacheBust){
                      src = cdc.includer.cacheBust(currentFile);
		}

		//if(cdc.includer.domainConfig.subdomains[0] == 'newsroom'){ host='newsroom.cisco.com'; }
		//cdc.debug.log('<strong>we are adding following domains in to array: </strong>: groups, services, products');
		//cdc.debug.log('<strong>we are removing following domains in to array: </strong>: services, products');
		//cdc.debug.log('<strong>Asset path before validation: </strong>'+host+' == '+src+' ==> '+cdc.includer.domainConfig.subdomains.join().indexOf(''+host.replace('.cisco.com.test',''))+' && '+src.indexOf('http'))

/*

- Validation for subdomain & absolute URL's:
- Validating the assets path with root relative URL's and hostname with array subdomains before appending the http://www.cisco.com.	

*/
		if((cdc.includer.domainConfig.subdomains.join().indexOf(''+host.replace('.cisco.com','')) != -1) && (src.indexOf('http') < 0)) {
			src = (document.location.protocol == 'http:')?'http://www.cisco.com'+src : 'https://www.cisco.com'+src;
		}
		
		//cdc.debug.log('<strong>Asset path after validation: </strong>'+host+' == '+src+' ==> '+cdc.includer.domainConfig.subdomains.join().indexOf(''+host.replace('.cisco.com.test',''))+' && '+src.indexOf('http'))
		//cdc.debug.log('<strong>Final list of domains in array object: </strong>'+cdc.includer.domainConfig.subdomains)
		scriptNode.src=src;
	};

	jQuery( function(){cdc.includer.search(cdc.includer.widgets)} );
}

/*
Method: cdc.includer.cacheBust()

Description:
- cache buster : puts a cache avoidance param on a url with a random number

Sample usages:
- cdc.includer.cacheBust('http://www.cisco.com');          = YourUrl?cacheReset=rand#
- cdc.includer.cacheBust('http://www.cisco.com','foo');    = YourUrl?foo=rand#
- cdc.includer.cacheBust('http://ng-prod1/image');         = YourUrl&cacheReset=rand#
- cdc.includer.cacheBust('http://cisco.com/edit.pl?a=3');  = YourUrl&cacheReset=rand#

*/
  cdc.includer.cacheBust = function(url,param){
    if (!param) {param = 'cacheReset'};
    var delim = "?";
    // if url is ng-prod1(bam) or has ?, set param delimeter to &
    if (url.match(/(ng-prod1|\?)/)) {delim = "&"};
    var fullParam = delim+param+'=';
    // degug alert(url+fullParam+cdc_rand_num());
    return url+fullParam+cdc.includer.cdcRandNum();
  };


/*
Method: cdc.includer.cdcRandNum()

Description:
- randum number generator
- input: takes param limit to set random max, default is 1000
- output: 'TimeInSeconds-RandNum'

Sample usages:
> invoke with: cdc.includer.randNum(50); or cdc_rand_num();

*/
  cdc.includer.cdcRandNum = function(limit){
    if (!limit) {limit = 1000};
    var sNum = Math.floor(Math.random()*limit)+1;
    var sTime = (new Date).getTime();
    var rNum = sTime+"-"+sNum;
    return rNum;
  };



if (typeof (cdc.util) == "undefined") cdc.util = {};

/*
Method: cdc.util.JsLoader()

Description:
-  there are four private methods of JsLoader.
- cdc.util.JsLoader.Load();
- cdc.util.JsLoader.loadOne();
- cdc.util.JsLoader.asuumeAlreadyLoaded();
- cdc.util.JsLoader._initialize();
- cdc.util.JsLoader._service();
*/

cdc.util.JsLoader = new function () {

    var _loadedUrls = null; // Map: loaded url -> 1, initially null to enable initialization
    var _pendingQueue = []; // Array: {url: pendingUrlString, callbacks: [ array of callbacks] }

    
    var _doLoad = function (jsUrls, callback, forceLoad, dataType) {
        if (_loadedUrls == null) _initialize();
        var _forceLoad = !!forceLoad;
        var _dataType = dataType;
        var processUrlAtIndex = function (jsUrls, index) {
            var addedCount = 0;
            if (index >= jsUrls.length) { // No more assets to load for this request
                if (typeof (callback) == "function") callback();
                return;
            }
            var url = jsUrls[index];
            if (typeof (_loadedUrls[url]) == "undefined" || _forceLoad) { // This asset is not yet loaded. Add it to the pending queue if needed.
                var ndx = index;
                var assetLoadedCallback = function () { processUrlAtIndex (jsUrls, ndx+1);  };
                var  pos = 0, m = _pendingQueue.length;
                for (; pos < m; pos++) {
                    if (_pendingQueue[pos].url === url) {
                        break;
                    }
                }
                if (pos >= m) { // This URL is not in the pending queue, so add it to the queue.                    
                    _pendingQueue.push ({ "url": url, "callbacks": [ assetLoadedCallback ], okToUseCache: true, dataType: _dataType });
                    addedCount = 1;
                } else { // This URL is already on the pending queue
                    _pendingQueue[pos].callbacks.push (assetLoadedCallback);
                }
            } else { // Already loaded, so ignore it and move on.
                addedCount += processUrlAtIndex (jsUrls, index+1);
            }
            return addedCount;
        };
        // Prime the pump
        jsUrls = (typeof (jsUrls) == "string") ? [ jsUrls ] : [].concat (jsUrls); // If it's an array, make a copy of it
        var queueWasEmpty = _pendingQueue.length <= 0;
        if (processUrlAtIndex (jsUrls, 0) > 0 && queueWasEmpty) {
            // The queue was initially empty, but I added stuff to it
            _service();
        }
        return this;
    };

	/*
Method: cdc.util.JsLoader.load()

Description:
-	Load the given list of JavaScript assets, in the order specified. If the callback is provided, call it after all the assets have been loaded. This
-	function takes care of multiple interleaved calls that might all specify common assets. If two callers specify assets in different orderings, the
-	ordering of the first such caller wins.
-	@param jsUrls an array of strings specifying JavaScript asset URLs
-	@param callback (optional) a function to call when all the specified assets have been loaded.
-	@param forceLoad (optional) boolean: true if the resource should be loaded even if it was already loaded earlier

*/
    this.load = function (jsUrls, callback, forceLoad) {
        if ((!jsUrls || jsUrls.length <= 0) && typeof (callback) == "function") {
            // No urls given, but callback specified, so the needed assets are (vacuously) loaded. So call the callback.
            callback();
            return;
        }
        _doLoad (jsUrls, callback, forceLoad, "script");
        return this;
    }


    
    // Load just one URL from a data service, with an optional parameter set. This method expects JSONP as the payload. This method caters to a common use case.
    
    this.loadOne = function (jsUrl, parameters, callback, forceLoad) {
        var url = jsUrl;
        if (parameters) {
            var separator = (jsUrl.indexOf ("?") > 0) ? "&" : "?";
            url += separator + jQuery.param (parameters);
        }
        return _doLoad ([ url ], callback, forceLoad, "json");
    };
    

    /*
     - Tell this loader to pretend that the given URLs are already loaded into the page, so they don't need to be reloaded.
     - @param jsUrls an array of asset URLs
     */
    this.assumeAlreadyLoaded = function (jsUrls) {
        jQuery.each (jsUrls, function (item) {
            _loadedUrls[item] = 1;
        });
    };

    // Private functions
    function _initialize () {
        // Remember the scripts loaded via explicit script tags
        _loadedUrls = {};
        jQuery("script").each (function (item) {
            var src = this.getAttribute ("src");
            if (src) _loadedUrls[src] = 1;
        });
    };
    
    function _service () {
        // Service one request, and invoke pseudo-recursively
        if (_pendingQueue.length >= 1) {
            var item = _pendingQueue[0];
            jQuery.ajax({
                type: "GET",
                url: item.url,
                dataType: item.dataType || "script",
                cache: item.okToUseCache,
                success: function (data) {
                    _loadedUrls[item.url] = 1;
                    _pendingQueue.shift();
                    for (var i = 0; i < item.callbacks.length; i++) {
                        item.callbacks[i]();
                    }
                    _service();
                }
            });
        }
    };

    return this;
};



/*
Method: cdc.includer.ServiceRequestQueue()

Description:
     - addRequest: Add a request for a data service.
     - @param url The URL of the service request
     - @param parameters the parameter set for the request: a map of strings to strings
     - @param callback the callback function to call when the request has been completed. This function will be called with the JSON data returned by the request.
     - @param okToUseCache (optional) a boolean value, set to true if the request may use an available cached version, i.e., a cache buster should be included; defaults to false
     - @param dataType  (optional) either "script" or "json" depending on the expected data type; defaults to "json"
     - This method is oriented towards a data service, hence its "okToUseCache" defaults to false.
*/

cdc.util.ServiceRequestQueue = function () {

    var _queue = [], _pending = false, _loadedUrls = {} /* For de-duplication of assets */;

    this.addRequest = function (url, parameters, callback, dataType, okToUseCache) {
        var dataTypeToUse = dataType  || "json";
        if (typeof (_loadedUrls[url]) == "undefined" || !okToUseCache) {
            _queue.push ({"url": url, "parameters": parameters, "callback": callback, "okToUseCache": !!okToUseCache, "dataType": dataTypeToUse});
            _loadedUrls[url] = 1;
            _service();
        }
    }


    // Return the number of requests currently in this queue.
    this.getQueueSize = function () {
        return _queue.length;
    }


    // Private functions
    function _service () {
        // Service one request, and invoke pseudo-recursively
        if (_queue.length >= 1 && !_pending) {
            _pending = true;
            var item = _queue[0];
            jQuery.ajax({
                type: "GET",
                url: item.url,
                data: item.parameters,
                dataType: item.dataType,
                cache: item.okToUseCache,
                success: function (data) {
                    item.callback (data);
                    _pending = false;
                    _queue.splice (0, 1);
                    _service();
                }
            });
        }
    }

};

