var Celebros_DataServerDNS = 'services.celebros.com';
var Celebros_WidgetsServerDNS = 'services.celebros.com';
var Celebros_ProductsJSONPage = '/JsonEndPoint/ProductsRecommendation.aspx';
var Celebros_ProductRecWidgetFile = '/Widgets/CelebrosProductRecommendationsWidget.js';
var Celebros_RequestType = 0;
// Default Product Url Mode
var Celebros_ProductsWidgetUrlMode = "QueryString";

var downloadedFiles = new Array();

var Celebros_DataRetrieved;
var Celebros_FirstCall = true;

//This allows trimming of strings without having to write out the function every time
String.prototype.trim = function() 
{
	return this.replace(/^\s+|\s+$/g,"");
}

// This function makes sure that the same file is included only once
function Celebros_includeOnce(sScriptFileName)
{
    if (downloadedFiles[sScriptFileName] != true) {
        downloadedFiles[sScriptFileName] = true;
        Celebros_include(sScriptFileName);
    }
}

// This function includes specified file
function Celebros_include(sScriptFileName)
{
    document.write('<sc' + 'ript');
    document.write(' language="javascript"');
    document.write(' type="text/javascript"');
    document.write(' id="CelebrosScript"');
    document.write(' src="' + sScriptFileName + '">');
    document.write('</sc' + 'ript>');
} 

// This function includes specified file
function Celebros_changeInclude(sScriptFileName)
{
    document.getElementById('CelebrosScript').setAttribute('src',sScriptFileName)
} 

// This function includes specified css file
function Celebros_includeCSS(sCSSFileName) 
{
    document.write('<l' + 'ink');
    document.write(' rel="stylesheet"');
    document.write(' type="text/css"');
    document.write(' href="' + sCSSFileName + '">');
}   

function Celebros_includeDOM(sScriptFileName) 
{
	var script = document.createElement('script');
	script.setAttribute('type', 'text/javascript');
    script.setAttribute('src', sScriptFileName);
	document.getElementsByTagName('head')[0].appendChild(script);
	return false;
}
 
// This function checks if the parameter is set 
function Celebros_isset(variable)
{
    return(typeof(variable)!='undefined');
}

// This method is passed to JSON page as a callback function
// and it's responsible for checking that the widget rendering function
// is already loaded and calling this function with the products recommendation result (JSON)
function Celebros_CallProductWidgetRenderer(ProductsRecommendationResult)
{
    if (typeof(Celebros_renderProductRecommendationsWidget) == 'undefined')
        throw "Product Recommendations Widget file wasn't loaded";
    Celebros_renderProductRecommendationsWidget(ProductsRecommendationResult)
}

            
// This functions gets recommended products from the recommendation engine
// and return JSON with the callback function call and the recommended products as a param
function Celebros_includeProductRecommendations(FunctionParams)
{
    var productsUrl = Celebros_getHttpPrefix();
    
    productsUrl += Celebros_GetProductsEndPointURL();
	    
	// add site key 
	productsUrl = Celebros_addURLParamToQueryString(productsUrl, 'siteKey', Celebros_Params.SiteKey);

	// add place holder id
    productsUrl = Celebros_addURLParamToQueryString(productsUrl, 'RequestHandle', Celebros_Params.Placeholder);
		
	// request type
	if (Celebros_isset(Celebros_Params.RequestType))
	    productsUrl = Celebros_addURLParamToQueryString(productsUrl, 'RequestType', Celebros_Params.RequestType);
    else 		    
	    productsUrl = Celebros_addURLParamToQueryString(productsUrl, 'RequestType', Celebros_RequestType);

	   
    // add product SKU (optional)
    if (Celebros_isset(Celebros_Params.SKU))    
        productsUrl = Celebros_addURLParamToQueryString(productsUrl, 'SKU', Celebros_Params.SKU);

    
    // add page encoding (optional)   
    var Encoding = Celebros_getCharset();
    
    if (Celebros_isset(Encoding))
        productsUrl = Celebros_addURLParamToQueryString(productsUrl, 'Encoding', Encoding);                
        
    if(FunctionParams) //Additional parameters, will be removed when all parameters will be passed directly. For now, this is used for paging and sorting
    {
        if(Celebros_isset(FunctionParams.Page))
            productsUrl = Celebros_addURLParamToQueryString(productsUrl, 'Page', FunctionParams.Page);
        if(Celebros_isset(FunctionParams.Sorting))        
            productsUrl = Celebros_addURLParamToQueryString(productsUrl, 'Sorting', FunctionParams.Sorting);
    }
	
//	// add number of products (optional)
//	if (Celebros_isset(Celebros_Params.NumOfProducts))
//		productsUrl = Celebros_addURLParamToQueryString(productsUrl, 'NumOfProducts', Celebros_Params.NumOfProducts);
	
	productsUrl = Celebros_addURLParamToQueryString(productsUrl, 'callback', 'Celebros_CallProductWidgetRenderer');
	
	if(Celebros_FirstCall)
	    Celebros_include(productsUrl);
	else
	    Celebros_changeInclude(productsUrl);
}

function Celebros_GetProductsEndPointURL()
{
    //if the user defined the dns in our parms
    if (Celebros_isset(Celebros_Params.DataServerDNS))
        return Celebros_Params.DataServerDNS + Celebros_ProductsJSONPage;
        
    //if we have the Conectivity object use it
    if (typeof CelebrosConectivity != 'undefined' &&
        Celebros_isset(CelebrosConectivity.DNS))
        return CelebrosConectivity.DNS + Celebros_ProductsJSONPage;
   
    //use the default 
	return Celebros_DataServerDNS + Celebros_ProductsJSONPage;
}

function Celebros_GetRecWidgetURL()
{
    //if the user defined the dns in our parms
    if (Celebros_isset(Celebros_Params.WidgetsServerDNS))
        return Celebros_getHttpPrefix() + Celebros_Params.WidgetsServerDNS + Celebros_ProductRecWidgetFile;
        
    //if we have the Conectivity object use it
    if (typeof CelebrosConectivity != 'undefined' &&
        Celebros_isset(CelebrosConectivity.DNS))
	    return Celebros_getHttpPrefix() + CelebrosConectivity.DNS + Celebros_ProductRecWidgetFile;
	
	//use the default     
    return Celebros_getHttpPrefix() + Celebros_WidgetsServerDNS + Celebros_ProductRecWidgetFile;
}

// This function encodes strings for URI
function Celebros_encodeURIComponent(str)
{
	if (typeof(encodeURIComponent) == 'function') 
	{
    	return encodeURIComponent(str);
	}
	else 
	{
    	return escape(str);
  	}
}

function Celebros_getCharset()
{
    //if we forced encoding return it
    if(Celebros_isset(Celebros_Params.Encoding))
        return Celebros_Params.Encoding;  
    
    //IE -not utf-8 send the encoding
    if(Celebros_isset(document.charset) && document.charset.toLowerCase() != "utf-8")
         return document.charset;
    
    //FireFox -not utf-8 send the encoding
    if(Celebros_isset(document.characterSet) && document.characterSet.toLowerCase() != "utf-8")
         return document.characterSet;
         
    return;
} 
// Adds the parameters to the URL by invoking the specified delegate on it.
function Celebros_addAllURLParams(sUrl, objParams, ParamAdderDelegate)
{
	for (var param in objParams)
	{
		sUrl = ParamAdderDelegate(sUrl, param, objParams[param]);
	}	
	return sUrl;
}

function Celebros_addURLParamsByMode(sUrl, objParams)
{
	// If there are parameters to add to the URL
	if (objParams)
	{
		
		switch(Celebros_Params.ProductUrlProperties.Mode.toLowerCase())
		{
			case "placeholders":
				sUrl = Celebros_addAllURLParams(sUrl, objParams, Celebros_replaceURLParamPlaceholder);			
				break;
			case "mask":
				sUrl = Celebros_addAllURLParams(sUrl, objParams, Celebros_addURLParamRewritten);			
				break;
			case "querystring":
			default:
				sUrl = Celebros_addAllURLParams(sUrl, objParams, Celebros_addURLParamToQueryString);
				break;
		}
	}
	return sUrl;
}

// This function adds a parameter and its value to URL query string. Can be used as a ParamAdderDelegate.
function Celebros_addURLParamToQueryString(sUrl, sParamName, sParamValue)
{
	if (sParamName) 
	{
		sUrl += (sUrl.indexOf("?") == -1 ? "?" : "&");
		sUrl += Celebros_encodeURIComponent(sParamName) + "=" + Celebros_encodeURIComponent(sParamValue);
	}
	return sUrl;
}

// This function adds a parameter and its value to URL as a rewritten URL (with slashes). Can be used as a ParamAdderDelegate.
function Celebros_addURLParamRewritten(sUrl, sParamName, sParamValue)
{
	if (sParamName && sUrl && sUrl.length > 0)
	{		
		// If the URL doesn't end with a slash then add one.
		if (sUrl.charAt(sUrl.length - 1) != "/")
		{
			sUrl += "/";
		}
		
		sUrl += Celebros_encodeURIComponent(sParamName) + "/" + Celebros_encodeURIComponent(sParamValue) + "/";
	}
	return sUrl;
}

// This function replaces a parameter's placeholder in a URL with its value. Can be used as a ParamAdderDelegate.
function Celebros_replaceURLParamPlaceholder(sUrl, sParamName, sParamValue)
{
	if (sParamName) 
	{
		// Create a regular expression that fits the placeholder and ignores case and matches all occurrences.
		var regexp = new RegExp("##" + sParamName + "##", 'gi');
		sUrl = sUrl.replace(regexp, Celebros_encodeURIComponent(sParamValue));
	}
	return sUrl;
}

// This function gets current http prefix
function Celebros_getHttpPrefix()
{
	if (window.location.protocol == "http:")
	{
    	sHttpPrefix = "http://";
	}
	else if (window.location.protocol == "https:")
	{
    	sHttpPrefix = "https://";
	}
	
	return sHttpPrefix;	
}

function isString (prop)
{
  return (typeof prop == 'string');
}


//check if Basic Params are defined or throw exception
function Celebros_checkBasicParams()
{
    if (!Celebros_isset(Celebros_Params))
	{
	    throw "Celebros_Params is undefined";
	}
	    
	if(!Celebros_isset(Celebros_Params.SiteKey))
	{
	    throw "SiteKey is undefined";
	}
	
	if(!Celebros_isset(Celebros_Params.Placeholder))
	{
	    throw "Placeholder is undefined";     
	}
	
	// Make sure ProductUrlProperties object is defined.
	if (!Celebros_isset(Celebros_Params.ProductUrlProperties))
	{
		Celebros_Params.ProductUrlProperties = new Object();
	}

	// Make sure the Mode is set to the default one.
	if (!Celebros_isset(Celebros_Params.ProductUrlProperties.Mode))
	{
		Celebros_Params.ProductUrlProperties.Mode = Celebros_ProductsWidgetUrlMode;
	}    
}

/**
 * Function to check that a string is harmless (no tag
 * injection).
 * @param value string Value to check.
 */
function validString(value) {
    return /^[^<>"]+$/.test(value);
}

/**
*function to go over all params to see that no string is potentially harmful(tag injection). 
*/
function Celebros_checkForInjection()
{
	var propValue;
	for(var object_properties in Celebros_Params)
	{
		propValue = Celebros_Params[object_properties];
	    if(isString(propValue) && !validString(propValue))
	        throw "parameter "+object_properties+ " is not valid"; 
    }
	
	for(var object_properties in Celebros_Params.ProductUrlProperties.Params)
	{
		propValue = Celebros_Params.ProductUrlProperties.Params[object_properties];
	    if(isString(propValue) && !validString(propValue))
	        throw "parameter "+object_properties+ " is not valid"; 
    }
}


// This is the main function responsible for product recommendations widget generation
function Celebros_generateProductRecommendationsWidget(AdditionalParams) 
{
	try 
	{
	    Celebros_checkBasicParams(); 
	    Celebros_checkForInjection();   
        Celebros_includeOnce(Celebros_GetRecWidgetURL());	        
        if(AdditionalParams) //For now, this means this is a postback. This will need to be changed when parameters will always be passed
            Celebros_includeProductRecommendations(AdditionalParams);
        else if(Celebros_DataRetrieved) //Use "cached" data
	        Celebros_CallProductWidgetRenderer(Celebros_DataRetrieved);
	    else
	        Celebros_includeProductRecommendations();
	}
	catch(err)
    {
        if (typeof Celebros_Params != 'undefined' && Celebros_Params.IsDebug)
        {
            txt="There was an error on this page.\n\n";
            txt+="Error description: " + err + err.description + "\n\n";
            txt+="Click OK to continue.\n\n";
            alert(txt);
        }
    }
}

// This is the main function responsible for product recommendations widget generation
function Celebros_generateWidget(Celebros_Params) 
{
	try 
	{
	    Celebros_checkBasicParams(); 
	    Celebros_checkForInjection();   
        Celebros_includeOnce(Celebros_GetRecWidgetURL());	        
	    Celebros_includeProductRecommendations();
	}
	catch(err)
    {
        if (typeof Celebros_Params != 'undefined' && Celebros_Params.IsDebug)
        {
            txt="There was an error on this page.\n\n";
            txt+="Error description: " + err + err.description + "\n\n";
            txt+="Click OK to continue.\n\n";
            alert(txt);
        }
    }
}




//Celebros_includeCSS(Celebros_getHttpPrefix() + 'services.celebros.com/ProductRecommendations/CelebrosStyle.css');