(function(){
	var rootNamespace = function(str,clean){
		var use = function (ns) {   
		  	if (typeof ns !== 'string' || ns.length === 0) {
		   		throw new Error('Invalid or empty namespace');
		  	}
		  	var root = window[str];
		  	ns = ns.split('.');
		  	for (var i = (ns[0] === str ? 1 : 0); i < ns.length; i++) {
		   		if (typeof root[ns[i]] === 'undefined') {
		    		root[ns[i]] = {};
		   		}
		   		root = root[ns[i]];
		  	}
		  	return root;
		};
	 
		var applyObj=function(base,over,write){
	 		for(var x in over){
		   		if( write || !(base[x]) ){
		    		base[x]=over[x];		  
		   		}else{
			   		throw new Error('Cannot overwrite '+ x +' in safe mode. It already exists in the namespace.');
		   		}
		  	}
		};
	 
		var resolveInterface=function(nsStr,fn,overWrite){
	 		var nsInterface={};
		  	if(typeof nsStr === 'string'){
		   		nsInterface.ns=nsStr;
		   		nsInterface.fn=fn;
		   		nsInterface.over=overWrite;
		  	}else if(typeof nsStr==='function'){
		   		nsInterface.ns=undefined;
		   		nsInterface.fn=nsStr;
		   		nsInterface.over=fn;		 
		  	}
		  	return nsInterface;	 
		};
	 
		var exec=function(nsStr,fn,overWrite){
	 		var x=resolveInterface(nsStr,fn,overWrite);
		  	var ns,fnResult;
		  	if(x.fn){
		   		fnResult=x.fn();
		  	}
		  	if(x.ns){
		   		ns=use(x.ns);
		  	}
		  	if(x.fn && x.ns){
		   		applyObj(ns,fnResult,x.over);
		  	}
		  	return (x.ns)?ns:fnResult;
		};
	 
		if(!window[str] || clean){
	 		window[str]=exec;
		  	window[str].Namespace={define:use};
		}else{
		  	throw new Error('this namespace already existed. Cannot Overwrite');
		}
	};
	rootNamespace('BN');
})();
/***
	Accepts global host obect
	ex. BN.Environment.Host.init({COMMUNITY: "my.barnesandnoble.com", SHOP: "cart2.barnesandnoble.com"});
***/
BN('Environment.Host', function(){
	//default domains does not yet include all, but maybe should...
	var hosts = {
		WEB: "www.barnesandnoble.com",
		SHOP: "cart2.barnesandnoble.com",
		NETORDERPATH: "cart4.barnesandnoble.com",
		STORELOCATOR: "store-locator.barnesandnoble.com",
		COMMUNITY: "my.barnesandnoble.com",
		MUSIC:'music.barnesandnoble.com',
		SEARCH:'search.barnesandnoble.com',
		IMAGEHOST:'images.barnesandnoble.com',
		VIDEO:'video.barnesandnoble.com',
		VIDEOGAME:'videogames.barnesandnoble.com',
		GIFTS:'gifts.barnesandnoble.com',
		SECURE:'secure.barnesandnoble.com',
		CROSSPRODUCT:'books.barnesandnoble.com'
	};
		
	var init = function(hostobj){
		if(!hostobj || typeof hostobj !== "object" || typeof hostobj === "function" || hostobj instanceof Array == true) {
			throw new Error('Host object initialization failed!');
		}else{
			hosts = hostobj;
		}
	};
	
	var iterator=function(fn){
		var arr=[];
		for(var x in hosts){
			if(hosts.hasOwnProperty(x)){
				arr[arr.length]=fn(x,hosts[x]);
			}
		}
		return arr;
	};


	var resolveDomain = function(hostName){
		var result;
		if(!hostName || !hosts[hostName.toUpperCase()]){
			throw new Error(hostName + ' is an invalid host name! eg. IMAGEHOST or MUSIC etc.');
		}else {
			result = hosts[hostName.toUpperCase()]; // make uppercase because it's a Constant
		}
		return result;
	};
		
	return {
		iterator:iterator,
		init: init,
		getMappedDomain: resolveDomain
	}
});

/***
	Accepts store object
	ex. BN.Environment.Store.init({storeId: "0002", storeCode: "hp"}); 
***/
BN('Environment.Store', function(){	
	var bnStore = true;
	var settings = {
		storeId: "0001",
		storeCode: "bn",
		storeName: "Barnes &amp; Noble"
	};
	var init = function(storeObject){
		for(var store in storeObject){
			if(storeObject[store] != '' && storeObject.hasOwnProperty(store) && settings[store]){
				settings[store] = storeObject[store];
			}
		}
		var code = settings['storeCode'];
		bnStore = code === 'bn' || code === '';
	};
	var getFnGen=function(n){
		return function(){
			return settings[n];
		};
	};
	return {
		init:init,
		isBN: function() { return bnStore; },
		getStoreId:getFnGen('storeId'),
		getStoreCode:getFnGen('storeCode'),
		getStoreName:getFnGen('storeName')
	}
});

/***
	Accepts host object for services only (optional)
	ex. BN.Environment.ServiceLink.init({SHOP: "cart2.barnesandnoble.com"}); see v6 for orig implementation
***/

BN('Environment.ImageLink', function(){
	var wlsStoreRef = '/white-label/stores/';
	var storeObj=BN.Environment.Store;
	var getHost=BN.Environment.Host.getMappedDomain;
	
	var getImageBridge = function(){
		return  (storeObj.getStoreId() !== "0001" && storeObj.getStoreId() != "")? wlsStoreRef + storeObj.getStoreCode(): '';
	};
	var getPath=function(host,subpath){
		var result='';
		var sec = (window.location.protocol === 'https:');
		//if only one param defined - as should be
		if(typeof subpath === 'undefined'){
			subpath=host;
		}
		//if at least one param is defined...
		if(typeof subpath !== 'undefined'){
			result = getImageBridge() + subpath;
			result = ( sec )? result : 'http://' + getHost("IMAGEHOST") + result;
		}else{
			throw new Error("image path requires a path to process");
		}
		return result;
	};
	return {
		getPath:getPath,
		getPathModifier:getImageBridge
	};
});
//this is to be removed when the bnfooter is updated to include manageconfig.js and 0001.js
BN('WL.Config.Text',function(){return{'ShortName':'BN.com','LongName':'Barnes &amp; Noble','StoreName':'Barnes &amp; Noble','ArchiveName':'Archive',
'Device': 'nook','DeviceLink': '<a href="http://www.barnesandnoble.com/nook/index.asp">|[{Device}]|</a>', 'EReaderSoftwareName': 'B&N eReader', 'PhoneNum': '1-800-THE-BOOK (1-800-843-2665)', 'PrivacyLink': '<a href="http://www.barnesandnoble.com/help/nc_privacy_policy.asp">Privacy Policy</a>', 'Copyright': '1997-2009 Barnesandnoble.com llc', 'ItemsFrom': 'Items from |[{StoreName}]|', 'ShippingOptionsLabel': 'Shipping Options &amp; Gift Preferences', 'ArchiveTitle': '|[{ArchiveName}]|', 'CancelledSub': 'You have cancelled your subscription. ', 'StaticMyUpdates': '', 'DigitalManagementTitle': 'Digital Management', 'DigitalManagementFirstColHeader': 'Digital Downloads', 'eBookStoreFront': 'Go to eBooks Storefront', 'eBookStaticAccordion': '<h3>Start reading your eBook</h3><p>Use your |[{Device}]| &amp; start reading.</p>', 'SelectDigitalOrderLabel': 'Download Digital Items', 'PageHeader': 'My Account', 'PageSignInHeader': 'Sign In or Create An Account','LockOutMessage':' ', 'CreateAccountBenefits': '<ul class="personalizeOptions"><li>Create and email your wish lists</li><li>Fill your virtual library</li><li>Share your reviews</li><li>Get updates on local store events</li></ul>', 'HowToPurchase': '', 'CreateAccountHeader': 'Create a Barnes &amp; Noble.com Account', 'CreateAccountInstructions': 'Fill in the fields below to create a Barnes &amp; Noble.com account. You\'ll be able to shop and check out faster on your next visit; check your order status online and receive updates on special offers and events. ', 'mainAccountFeatureTxt': '', 'BNUserInstructions': '', 'DeliveryDetailsLabel': 'Delivery &amp; Gift Details', 'OnlinePriceLabel': 'Online Price', 'EBookOnlinePriceLabel': 'eBook Price', 'SignIn': { 'AccountBenefits': '<h2>Sign up now and enjoy these benefits:</h2><p class="errors" ></p><div id="newCustomersCopy"><ul><li>Create and email your wish lists</li><li>Champion your favorite titles</li><li>Fill your virtual library</li><li>Share your reviews</li><li>Get updates on local store events</li></ul></div>', 'LearnAboutBN': '<a href="http://|!P{WebDomain}P!|/my-bn/">Learn more about My B&amp;N</a>', 'CreateAccountInstructions': 'If you already have an account, please <a href="#" class="signInLink">sign in</a>.'}}
}, true);
BN('Text.Tokenizer',function(){
	var TokenProcessor=function(s,e){
		var start=s||'{';
		var end = e||'}';
		var template=undefined;
		var setStart=function(sta){
			if(sta !== end){
				start=sta;
			}else{
				throw 'token start cant match token end';
			}
		};
		
		var setEnd=function(nd){
			if(nd !== start){
				end=nd;
			}else{
				throw 'token start cant match token end'; 
			}
		};
		
		var setSource= function(obj){
			template=obj;
		};
		
		var tokenize=function(str,tem){
			var sorce=tem || template;
			var arr=str.split(start);
			var temp='';
			if(sorce === undefined){
				throw 'tokenizer requires source to match against';
			}
			for(var i=1;i<arr.length;i++){
				temp=arr[i].split(end);
				arr[i]=sorce[temp[0]]+(temp[1] || '');
			}
			return arr.join('');			
		};

		return{
			setStart:setStart,
			setEnd:setEnd,
			setData:setSource,
			process:tokenize
		};
	};
	
	return {
		getTokenizer:function(s,e){
			return new TokenProcessor(s,e);
		}
	}
},true);

BN('Environment.Text',function(){
	var dataSource=BN.WL.Config.Text;
	
	//this will be removed
	var doRecursiveReplace=function(txt){
		var flatten=function(n){
		    var flatObj={};
		    var iterate=function(obj,str){
		        var myStr=str ||'';
		        for(var x in obj){
		            if(obj.hasOwnProperty(x)){
		                if(typeof obj[x] === 'string'){
		                    flatObj[myStr+x]=obj[x];
		                }else{
		                    iterate(obj[x],myStr+x+'.');
		                }
		            }
		        }
		    };
	    	iterate(n);
	    	return flatObj;
		};
		var tokenizer = BN.Text.Tokenizer.getTokenizer('|[{','}]|');
		var result = tokenizer.process(txt,flatten(dataSource));
		return result;
		
	};
	
	

	var findText=function(str,obj){
	    var pos=str.indexOf('.');
	    if(pos !== -1){
	        return findText(str.substring(pos+1),obj[str.substring(0,pos)])
	    }else{
	        if(typeof obj[str] === 'string'){
	            return obj[str];
	        }else{
	            throw str + ' is not a string. Replacement must terminate with a string';
	        }
	    }
	};
	
	var replaceText= function(txt,sorc){
		var tokenizer = BN.Text.Tokenizer.getTokenizer('|!P{','}P!|');
		return tokenizer.process(txt,sorc);
	};
	
	var locGetText=function(lookup,replaceObj){
		var result= findText(lookup,dataSource);
		if(replaceObj){
			result=replaceText(result,replaceObj);
		}
		//this does the token replacement....
		
		return doRecursiveReplace(result);
		//Following is after replacement is done in the tool.
		//return result;
	};
	
	return {getText:locGetText};	
},true);

