var _itemPageRegister={};
var _items={};
var _skins={};
var _configTable={};
var _ratingConfigCount = 0;
var _cs_del = "-|-";
var _id_del = "-x-";
var _ratingSkinPath = "/ContentRatingResourceFiles/Scripts/Simple/RatingSkin.js";
var _idAddOnImageRatings = 'RatingsImage';
// the below two variables are now getting added by the rating server control that is dropped on the master pages
//var _ratingsWebRelativeURL = "";
//var _servicePrefix;

/******************************************************************
Core UI tokens
******************************************************************/
var _totalRatingsToken='@totalRatings#';
var _averageRoundedRatingsToken='@averageRoundedRatings#';
var _averageRatingsToken='@averageRating#';
var _controlIdToken='@itemId#';
var _myRatingToken='@myRating#';
var _configKeyToken='@configKey#';
var _idPrefixEnableUsefulness='enableUsefulness';
var _idPrefixRatingDisplayAverageRating='ratingDisplayAverageRating';
var _idPrefixRatingDisplayTotalRatings='ratingDisplayTotalRatings';
var _idPrefixRatingDisplayMyRating='ratingDisplayMyRating';
var _idPrefixRatingDisplayPopupCommentControl='ratingDisplayPopupCommentControl';
var _idPrefixCommentDisplayAverageRating='commentDisplayAverageRating';
var _idPrefixCommentDisplayTotalRatings='commentDisplayTotalRatings';
var _idPrefixCommentDisplayMyRating='commentDisplayMyRating';

/******************************************************************
Core UI rendering functions
******************************************************************/
function AddJavaScriptRatingSkinReference(path, elementid)
{
	var ns = document.createElement('script');
	ns.setAttribute('type', 'text/javascript');
	ns.setAttribute('language', 'javascript');
	ns.setAttribute('id', elementid);
	document.getElementsByTagName('head')[0].appendChild(ns);
	document.getElementById(elementid).src = path;
}
function SetRelUrl()
{
	if(_ratingsWebRelativeURL == "")
	{
		var re = /'(.*?)'/;
		var func = WebForm_OnSubmit.toString();
		var site = func.match(re);
		_ratingsWebRelativeURL= site[0].substring(1, site[0].length - 1);
		_servicePrefix = _ratingsWebRelativeURL.replace(/\\u002f/g, "/");
		_ratingsWebRelativeURL = _servicePrefix;
		
		if(_servicePrefix == "/")
			_servicePrefix = "/_layouts/Service.Ratings";
		else
		{
			_servicePrefix = _servicePrefix + "/_layouts/Service.Ratings";
		}	
	}
}

AddJavaScriptRatingSkinReference(_ratingSkinPath, 'ratingskin');


// this call is coming from a search page ns_scope
function renderRatingControls(configurationName,contentSourceId)
{
	var controlid;
	var config = Config.GetInstance(configurationName, false);
	if(config.error.number>0){alert(config.error.message);return;}
	
	var configKey = contentSourceId + _cs_del + _ratingConfigCount;
	_configTable[configKey] = config;	

	if (config!=null)
	{
		var itemIds = _itemPageRegister[_ratingConfigCount];
		var list = itemIds.join(',');
		config.ratedItems = RatedItemCollection.GetInstance(contentSourceId, list);
		config.ratings = RatingCollection.GetInstance(contentSourceId, list, true);
		
        for(var i = 0; i < itemIds.length; i++)
        {
			controlid = configKey + _id_del + itemIds[i];
			currentControl = document.getElementById(controlid);			
			var ratedItem = config.ratedItems.GetItem(itemIds[i]);
			
			//if ratedItem not found in database, add to the ratedItems
			if(ratedItem == null)
			{
				ratedItem = RatedItem.GetInstance(contentSourceId, itemIds[i], _items[itemIds[i]].itemTitle, _items[itemIds[i]].itemUrl, 0, 0);
				config.ratedItems.AddItem(ratedItem);
			}
			else if(ratedItem.title == '')
			{
				ratedItem.title = _items[itemIds[i]].itemTitle;
				ratedItem.url = _items[itemIds[i]].itemUrl;
			}
			var averageRoundedRating = computeRoundedAverageRating(ratedItem.averageRating);
			ratedItem.controlPrefix = controlid;

			currentControl.innerHTML = tokenReplace(config.ratingSkinHtml 
				, _totalRatingsToken, ratedItem.totalRatings 
				, _averageRoundedRatingsToken, averageRoundedRating 
				, _averageRatingsToken, ratedItem.averageRating 
				, _controlIdToken, ratedItem.controlPrefix
				,_configKeyToken, configKey);

    		renderRatingsImagesById(ratedItem.controlPrefix + _idAddOnImageRatings, averageRoundedRating*2, "rated");
 			applyControlMasking(ratedItem.controlPrefix);
        }		
	}
	_ratingConfigCount = _ratingConfigCount + 1;
}
var _listMetadata = null;
var _fetchOnce = true;
var _listWebUrl = null;

function renderListRatingControl(listGuid, ratingContent, itemId, title, url, configurationName, webId)
{
	if (ratingContent=="")
		ratingContent = "0,0";
	var AverageRating = parseNumber(ratingContent.split(",")[0]);
    var TotalRatings = parseNumber(ratingContent.split(",")[1]);
    var contentSourceId = null;
    var configKey = null;    
	var config = null;

    if (_listMetadata==null || _listMetadata[listGuid + _ratingConfigCount]==null)
    {
		 _listMetadata = {};
		 _listMetadata[listGuid + _ratingConfigCount] = {};
    	if (webId==null)
    	{    		
		    var indexVtiBin = ctx.HttpPath.indexOf('_vti_bin');
		    _listWebUrl = ctx.HttpPath.substring(1,indexVtiBin);
		    contentSourceId = (replaceString('/',_id_del,_listWebUrl) + "@" + listGuid);	 		 		
			config = Config.GetInstance(contentSourceId, true);
			webId = "{" + config.webId + "}";
		}
		else
			config = Config.GetInstance(configurationName, false);			
		
		if(config.error.number>0){alert(config.error.message);return;}
			
		_listMetadata[listGuid + _ratingConfigCount].contentSourceId = (webId + "@" + listGuid);
		configKey = _listMetadata[listGuid + _ratingConfigCount].contentSourceId + _cs_del + _ratingConfigCount;
		_configTable[configKey] = config;
    }
   
    contentSourceId = _listMetadata[listGuid + _ratingConfigCount].contentSourceId;
    configKey = contentSourceId + _cs_del + _ratingConfigCount;
    
    var ratedItem = RatedItem.GetInstance(contentSourceId , itemId, title, url, AverageRating, TotalRatings);
    ratedItem.controlPrefix = contentSourceId + _cs_del + _ratingConfigCount + _id_del + itemId;
    _configTable[configKey].ratedItems.AddItem(ratedItem);
    _configTable[configKey].ratings.contentSourceId = contentSourceId;
    _configTable[configKey].ratings.AddItemId(itemId);
    
    var averageRoundedRating = computeRoundedAverageRating(ratedItem.averageRating);

    var renderedHtml =  tokenReplace(_configTable[configKey].ratingSkinHtml
    								, _totalRatingsToken, TotalRatings
    								, _averageRoundedRatingsToken, averageRoundedRating
    								, _averageRatingsToken, AverageRating
    								, _controlIdToken, ratedItem.controlPrefix
    								,_configKeyToken, configKey);
    document.write("<div id='" + ratedItem.controlPrefix + "'>" + renderedHtml + "</div>");
    
    renderRatingsImagesById(ratedItem.controlPrefix + _idAddOnImageRatings, averageRoundedRating*2, "rated");
	applyControlMasking(ratedItem.controlPrefix);
}

function LoadContentRatingReview(parentConfiguration, skinType, webPartId, querystringParameterNameContentSourceId, querystringParameterNameItemId,
							contentSourceId, itemId, averageRating, totalRatings, providerWebPartId)
{
	var ratedItem = null;
	var ratings;
    computeQueryString();
 	
 	var wepPart = document.getElementById(webPartId);
		
	//remove all children
	if ( wepPart.hasChildNodes() )
	    while ( wepPart.childNodes.length >= 1 )
	        wepPart.removeChild(wepPart.firstChild); 

	if	(contentSourceId!=null && itemId!=null && averageRating!=null && totalRatings!=null)
	{
		ratedItem = RatedItem.GetInstance(contentSourceId , itemId, document.nameProp, window.location.href.replace(window.location.search,""), averageRating, totalRatings);
		ratedItem.controlPrefix = contentSourceId + _cs_del + _ratingConfigCount + _id_del + itemId;
        ratings = RatingCollection.GetInstance(contentSourceId, itemId, true);
	}      
    else if (qsParm[querystringParameterNameContentSourceId]!=null && qsParm[querystringParameterNameItemId]!=null)
    {
        ratedItem = RatedItem.GetInstance(qsParm[querystringParameterNameContentSourceId],qsParm[querystringParameterNameItemId]);
        ratedItem.controlPrefix = ratedItem.contentSourceId + _cs_del + _ratingConfigCount + _id_del + ratedItem.itemId;
        ratings = RatingCollection.GetInstance(ratedItem.contentSourceId, ratedItem.itemId, true);
    }
    else if (qsParm["averageRating"]!=null && qsParm["totalRatings"]!=null)
    {
        ratedItem = RatedItem.GetInstance(parentConfiguration,webPartId,"dummyTitle",window.location.href,qsParm["averageRating"],qsParm["totalRatings"]);
        document.getElementById(webPartId).innerHTML = "<div><b>AverageRating and TotalRatings consumed from QueryString</b></div></br>";
        ratedItem.controlPrefix = _ratingConfigCount + _id_del + webPartId;
    }
    else
    {
        ratedItem = RatedItem.GetInstance(parentConfiguration,webPartId,"dummyTitle","dummyUrl",3.5,88);
        document.getElementById(webPartId).innerHTML = "<div><b>Avg. and Total Dummy Values</b></div></br>";
        ratedItem.controlPrefix = _ratingConfigCount +  _id_del + webPartId;
    }
    
    var configKey = ratedItem.controlPrefix.split(_id_del)[0];
    var config = Config.GetInstance(parentConfiguration, false);
 	if(config.error.number>0){alert(config.error.message);return;}
 	config.ratedItems.AddItem(ratedItem);
    config.ratings = ratings;
	config.providerWebPartId = providerWebPartId;
    _configTable[configKey] = config;

    hideDisplayUsefullness(providerWebPartId,contentSourceId,configKey);
    
    var averageRoundedRating = computeRoundedAverageRating(ratedItem.averageRating);
    
    if (skinType == "Combined")
    {
    	var divElement = document.createElement("DIV");
		divElement.id = ratedItem.controlPrefix;
        divElement.innerHTML = tokenReplace(_configTable[configKey].ratingSkinHtml
                                    , _totalRatingsToken, ratedItem.totalRatings
                                    , _averageRoundedRatingsToken, averageRoundedRating
                                    , _averageRatingsToken, ratedItem.averageRating
                                    , _controlIdToken, ratedItem.controlPrefix
                                    ,_configKeyToken, ratedItem.controlPrefix.split(_id_del)[0]);
		wepPart.appendChild(divElement);
		renderRatingsImagesById(ratedItem.controlPrefix + _idAddOnImageRatings, averageRoundedRating*2, "rated");
	    applyControlMasking(ratedItem.controlPrefix);

	    divElement = document.createElement("DIV");
	    divElement.id = 'divcommentBaked' + ratedItem.controlPrefix;
        divElement.innerHTML = tokenReplace(_configTable[configKey].commentSkinHtml
                                    , _totalRatingsToken, ratedItem.totalRatings
                                    , _averageRoundedRatingsToken, averageRoundedRating
                                    , _averageRatingsToken, ratedItem.averageRating
                                    , _controlIdToken, 'divcommentBaked' + ratedItem.controlPrefix
                                    ,_configKeyToken, ('divcommentBaked' + ratedItem.controlPrefix).split(_id_del)[0]);
        wepPart.appendChild(divElement);
	    applyControlMasking('divcommentBaked' + ratedItem.controlPrefix);
	    _configTable[configKey].controls = "Combined";    
	}
    else if (skinType == "Rating")
    {
    	var divElement = document.createElement("DIV");
		divElement.id = ratedItem.controlPrefix;
		divElement.innerHTML = tokenReplace(_configTable[configKey].ratingSkinHtml
                                    , _totalRatingsToken, ratedItem.totalRatings
                                    , _averageRoundedRatingsToken, averageRoundedRating
                                    , _averageRatingsToken, ratedItem.averageRating
                                    , _controlIdToken, ratedItem.controlPrefix
                                    ,_configKeyToken, ratedItem.controlPrefix.split(_id_del)[0]);
		wepPart.appendChild(divElement);	
		renderRatingsImagesById(ratedItem.controlPrefix + _idAddOnImageRatings, averageRoundedRating*2, "rated");
	    applyControlMasking(ratedItem.controlPrefix);
	    _configTable[configKey].controls = "Rating";                          
    }
    else
    {
    	var divElement = document.createElement("DIV");
    	ratedItem.controlPrefix = 'divcomment' + ratedItem.controlPrefix;
    	divElement.id = ratedItem.controlPrefix;
        divElement.innerHTML += tokenReplace(_configTable[configKey].commentSkinHtml
                                    , _totalRatingsToken, ratedItem.totalRatings
                                    , _averageRoundedRatingsToken, averageRoundedRating
                                    , _averageRatingsToken, ratedItem.averageRating
                                    , _controlIdToken, ratedItem.controlPrefix
                                    ,_configKeyToken, ratedItem.controlPrefix.split(_id_del)[0]);
        wepPart.appendChild(divElement);
	    applyControlMasking(ratedItem.controlPrefix);
	    _configTable[configKey].controls = "Comment";
	}    
    _ratingConfigCount ++;
}

function tokenReplace(html)
{
	var	controlHtml = html;
	for(var i = 1; i < arguments.length - 1; i+=2)
	{
		controlHtml= replaceString(arguments[i], arguments[i + 1], controlHtml);
	}
	return controlHtml;
}

function replaceString(oldString,newString,str)
{
    var reg = new RegExp('(' + oldString + ')', 'gi');
    return str.replace(reg, newString);
}

function AddRatingsControl(contentSourceId, itemId, title, url)
{ 
	if(typeof(_itemPageRegister[_ratingConfigCount]) == 'undefined')
	{
		_itemPageRegister[_ratingConfigCount]=[];
		_items = {};
	}
	_itemPageRegister[_ratingConfigCount].push(itemId);
		
	var cid=_ratingConfigCount + _id_del + itemId;
	_items[itemId] = {itemUrl:url, itemTitle:title};
    document.write('<div id=' + contentSourceId + _cs_del + cid + '></div>');	
}

function applyControlMasking(controlId,isConfigPage,configKey)
{
	var comp;
	if (isConfigPage==null)	
		comp = controlId.split(_id_del);
	else if (isConfigPage)
		comp = controlId.split(_cs_del);
	if (configKey == null)
		configKey = comp[0];

	applyMasking(_idPrefixEnableUsefulness + controlId, "EnableUsefulness", configKey);
	applyMasking(_idPrefixRatingDisplayAverageRating + controlId, "RatingDisplayAverageRating", configKey);
	applyMasking(_idPrefixRatingDisplayTotalRatings + controlId, "RatingDisplayTotalRatings", configKey);
	applyMasking(_idPrefixRatingDisplayMyRating + controlId, "RatingDisplayMyRating", configKey);
	applyMasking(_idPrefixRatingDisplayPopupCommentControl + controlId, "RatingDisplayPopupCommentControl", configKey);
	applyMasking(_idPrefixCommentDisplayTotalRatings + controlId, "CommentDisplayTotalRatings", configKey);
	applyMasking(_idPrefixCommentDisplayAverageRating + controlId, "CommentDisplayAverageRating", configKey);
	applyMasking(_idPrefixCommentDisplayMyRating + controlId, "CommentDisplayMyRating", configKey);
}

function applyMasking(controlId, configProperty, configKey)
{
	if (document.getElementById(controlId)!=null)
		if (!_configTable[configKey][configProperty])
		    document.getElementById(controlId).style.display = "none";
	    else
		    document.getElementById(controlId).style.display = "inline";
}

/******************************************************************
End core UI rendering functions
******************************************************************/


/******************************************************************************
//Core rating objects
******************************************************************************/
function addMethod(object, name, fn){
    var old = object[ name ];
    object[ name ] = function(){
        if ( fn.length == arguments.length )
            return fn.apply( this, arguments );
        else if ( typeof old == 'function' )
            return old.apply( this, arguments );
    };
}

Serializable = function(){}
Serializable.prototype.Type = function()
{
	re = /\/\/\[Type:\w*/;
	var arr = this.constructor.toString().match(re);
	return arr[0].split(":")[1];
}
Serializable.prototype.SerializableProperties = function()
{
	var re = /\/\/\[Serializable:\[(.*?)\]/;
	var arr = this.constructor.toString().match(re);
	return eval(arr[0].split(":")[1]);
}

Serializer = function(){}
Serializer.prototype.Deserialize = function(o, node)
{
	var p = o.SerializableProperties();
	for(var i = 0; i < p.length; i++)
	{
		o[p[i]] = this.Deserialize2(o[p[i]], node.selectSingleNode(p[i]));
	}
	return o;
}
Serializer.prototype.Deserialize2 = function(prop, node)
{
	switch (typeof(prop))
	{
		case "string":
			return node.text;
		case "number":
			return parseNumber(node.text);
		case "boolean":
			return node.text =='false'?false:true;
		case "object":
			//Array
			if(prop.constructor.toString().indexOf("function Array()") > -1)
			{
				for(var i = 0; i < node.childNodes.length; i++)
				{
					var mem = InitValue(prop.Type); //TODO
					mem = this.Deserialize(mem, node.childNodes[i]);
					prop.push(mem);
				}
				return prop;
			}
			else if(prop.constructor.toString().indexOf("function Date()") > -1)
			{
                return new Date(parseNumber(node.text))
			}
			else
			{
			//object
				return this.Deserialize(prop, node)
			}
	}
}
Serializer.prototype.Serialize = function(o, name)
{
	var xml = "<" + name + ">";
	switch (typeof(o))
	{
		case "string":
			xml += "<![CDATA[" + o + "]]>";
			break;
		case "number":
		case "boolean":
			xml += o;
			break;
		case "object":
			//Array
			if(o.constructor.toString().indexOf("function Array()") > -1)
			{
				for(var i = 0; i < o.length; i++)
				{
					if(typeof(o[i]) == 'object')
					{
						xml += this.Serialize(o[i], o[i].Type());
					}
					else
					{
						xml += this.Serialize(o[i], typeof(o[i]));
					}
				}
			}
			else if(o.constructor.toString().indexOf("function Date()") > -1)
			{
                xml+= o.toUTCString();
			}
			else //object
			{
				var p = o.SerializableProperties();
				for(var j = 0; j < p.length; j++)
				{
					xml += this.Serialize(o[p[j]], p[j]);
				}
			}
	}
	xml += "</" + name + ">";
	return xml;
}
var s = new Serializer();
function parseNumber(n)
{
	if(n.toString().indexOf("."))
		return parseFloat(n);
	else
		return parseInt(n);
}
function InitValue(t)
{
	switch (t)
	{
		case "string":
			return '';
		case "number":
			return 0;
		case "boolean":
			return false;
		default:
			return eval("new " + t + "()");
	}		
}

//== base class ==
function Service()
{
	this.xmlhttp = null;
	this.xmldoc = null;
	this.serviceUri = '';
	this.error = new RatingServiceError();
	this.OnUpdate = [];
    this.Load = function()
    {
		s.Deserialize(this, this.xmldoc);
    }
	this.getResponse = function()
	{
		if (this.xmlhttp.readyState == 4)
		{
			this.xmldoc = this.xmlhttp.responseXML.documentElement;
			this.Load();
			for(var i = 0; i < this.OnUpdate.length; i++)
				this.OnUpdate[i](this);
		}
	};
}
Service.FirstRequest = true;
Service.prototype = new Serializable;
Service.prototype.constructor = Service;
Service.prototype.Call = function(verb, msg, async)
{
	if(verb.toLowerCase() == 'post')
	{	
		if(Service.FirstRequest)
		{
			UpdateFormDigest(_ratingsWebRelativeURL, 0);
			Service.FirstRequest = false;
		}
		else
			UpdateFormDigest(_ratingsWebRelativeURL, 1440000);

		//Adds new form digest to body of the message of XMLHttp object
		msg += "&__REQUESTDIGEST=" + document.forms[0]["__REQUESTDIGEST"].value;

	}
	if (window.XMLHttpRequest) //IE7
	{
		this.xmlhttp = new XMLHttpRequest();
	}
	else //IE5, IE6
	{
		var ua = navigator.userAgent.toLowerCase();
		if (ua.indexOf('msie 5') == -1)
			this.xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
		else
			this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
	}


	if(async)
	{
		var r = this.closure(this);
		this.xmlhttp.open(verb, this.serviceUri, async);
		this.xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
		this.xmlhttp.onreadystatechange = r;
		this.xmlhttp.send(msg);
	}
	else
	{
		this.xmlhttp.open(verb, this.serviceUri, async);
		this.xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
		this.xmlhttp.send(msg);
		this.xmldoc = this.xmlhttp.responseXML.documentElement;
		if(this.xmlhttp.status != 200)
			if(this.xmldoc!=null)
				s.Deserialize(this.error, this.xmldoc);
			else
				alert('The rating service does not exist');
	}
}
Service.prototype.closure = function(ob)
{
	return function(){ob.getResponse();}
}
Service.prototype.Xml = function()
{
	return s.Serialize(this, this.Type());
}
//== end base class ==

function RatingServiceError()
{
	//[Type:RatingServiceError]
	//[Serializable:["number", "message", "url"]]
	this.number = 0;
	this.message = '';
	this.url = '';
}
RatingServiceError.prototype = new Serializable;
RatingServiceError.prototype.constructor = RatingServiceError;

function Config()
{
	//[Type:Config]
	//[Serializable:["EnableRerating", "EnableUsefulness", "RatingDisplayTotalRatings", "RatingDisplayAverageRating", "RatingDisplayMyRating", "RatingDisplayPopupCommentControl", "CommentDisplayTotalRatings", "CommentDisplayAverageRating", "CommentDisplayMyRating", "RaterSkin", "CommentSkin", "Namespace", "isDefault", "ratingSkinHtml", "commentSkinHtml", "webId"]]
    this.EnableRerating = false;
    this.EnableUsefulness = false;
	this.RatingDisplayTotalRatings = false;
	this.RatingDisplayAverageRating = false;
	this.RatingDisplayMyRating = false;
	this.RatingDisplayPopupCommentControl = false;
	this.CommentDisplayTotalRatings = false;
	this.CommentDisplayAverageRating = false
	this.CommentDisplayMyRating = false;
    this.RaterSkin = '';
    this.CommentSkin = '';
    this.Namespace= '';
    this.isDefault= false;
    this.ratingSkinHtml = '';
    this.commentSkinHtml = '';
    this.webId = '';
    
    this.ratedItems = new RatedItemCollection();
    this.ratings = new RatingCollection();
    this.configId;
}
Config.prototype = new Service;
Config.prototype.constructor = Config;
Config.prototype.Update = function(async)
{
	this.serviceUri = _servicePrefix + "/Config/?url=" + encodeURIComponent(this.Namespace);
	var msg = "xml=" + encodeURIComponent(this.Xml());
	this.Call("POST", msg, async);
	if(this.error.number > 0)return
	if(!async)s.Deserialize(this, this.xmldoc);
}
Config.prototype.Fetch = function(configurationId, isListId, async)
{	
	this.Namespace = configurationId;
	this.serviceUri = _servicePrefix + "/Config/" + encodeURIComponent(configurationId) + "/?isListId=" + isListId;
	this.Call("Get", "", async);
	if(this.error.number > 0)return;
	if(!async)s.Deserialize(this, this.xmldoc);
}
addMethod(Config, "GetInstance", function(node){
  var o = new Config();
  o.xmldoc = node;
  s.Deserialize(o, o.xmldoc);
  return o;
});
addMethod(Config, "GetInstance", function(){
  var o = new Config();
  return o;
});
addMethod(Config, "GetInstance", function(configurationName, isList){
  	var o = new Config();
	o.Fetch(configurationName, isList, false);
  	return o;
});

function Skin()
{
	//[Type:Skin]
	//[Serializable:["html"]]
    this.html = '';
    this.name = '';
    this.skinType = '';
}
Skin.prototype = new Service();
Skin.prototype.constructor = Skin;
Skin.prototype.Fetch = function(async)
{
	this.serviceUri = _servicePrefix + "/skins/" + this.skinType + "/" + encodeURIComponent(this.name);
	this.Call("Get", "", false);
	if(this.error.number > 0)return;
	if(!async)s.Deserialize(this, this.xmldoc);
}
addMethod(Skin, "GetInstance", function(skinName, skinType){
  var o = new Skin();
  o.name = skinName;
  o.skinType = skinType;
  o.Fetch(false);
  return o;
});


function RatedItem()
{
	//[Type:RatedItem]
	//[Serializable:["contentSourceId", "itemId", "title", "url", "averageRating", "totalRatings"]]
	this.contentSourceId = '';
	this.itemId = '';
	this.title = '';
	this.url = '';
    this.averageRating = 0;
    this.totalRatings = 0;
    
    this.controlPrefix = '';
}
RatedItem.prototype = new Service;
RatedItem.prototype.constructor = RatedItem;
RatedItem.prototype.Update = function(async)
{
	this.serviceUri = _servicePrefix + "/rateditems/" + encodeURIComponent(this.contentSourceId) + "/" + this.itemId;
	var msg = "xml=" + encodeURIComponent(this.Xml());
	this.Call("POST", msg, false);
	if(this.error.number > 0)return;
	if(!async)this.Load();
}
RatedItem.prototype.Fetch = function(async)
{
	this.serviceUri = _servicePrefix + "/rateditems/" + encodeURIComponent(this.contentSourceId) + "/" + this.itemId;
	this.error.number = 0;
	this.Call("GET", "", async);
	if(this.error.number > 0)return;
	if(!async)this.Load();
}
addMethod(RatedItem, "GetInstance", function(node){
  var o = new RatedItem();
  o.xmldoc = node;
  o.Load(); 
  return o;
});
addMethod(RatedItem, "GetInstance", function(contentSourceId, itemId, title, url, averageRating, totalRatings){
  var o = new RatedItem();
  o.contentSourceId = contentSourceId
  o.itemId = itemId;
  o.title = title;
  o.url = url;
  o.averageRating = averageRating;
  o.totalRatings = totalRatings;
  return o;
});
addMethod(RatedItem, "GetInstance", function(contentSourceId, itemId){
  var o = new RatedItem();
  o.contentSourceId = contentSourceId;
  o.itemId = itemId
  o.Fetch(false);
  return o;
});
addMethod(RatedItem, "GetInstance", function(contentSourceId, itemId, callback){
  var o = new RatedItem();
  o.contentSourceId = contentSourceId;
  o.itemId = itemId
  o.OnUpdate.push(callback);
  o.Fetch(true);
  return o;
});

function Rating()
{
	//[Type:Rating]
	//[Serializable:["contentSourceId", "itemId", "ratingid", "rating", "comment", "positiveevals", "totalevals", "totalcomments","createdDate", "userAccount"]]
    this.contentSourceId = '';
    this.itemId = '';
    this.ratingid = 0;
    this.rating = 0;
    this.comment = '';
	this.positiveevals = 0;
    this.totalevals = 0;
	this.totalcomments = 0;
	this.createdDate = new Date();
    this.userAccount = new UserAccount();
}
Rating.prototype = new Service;
Rating.prototype.constructor = Rating;
Rating.prototype.Update = function(async)
{
	this.serviceUri = _servicePrefix + "/rateditems/" + encodeURIComponent(this.contentSourceId) + "/" + this.itemId + "/user";
	var msg = "xml=" + encodeURIComponent(this.Xml());
	this.Call("POST", msg, false);
	if(this.error.number > 0)return;
	if(!async)this.Load();
}
Rating.prototype.Fetch = function(async)
{
	this.serviceUri = _servicePrefix + "/rateditems/" + encodeURIComponent(this.contentSourceId) + "/" + this.itemId + "/user";
	this.Call("GET", "", async);
	if(this.error.number > 0)return;
	if(!async)this.Load();
}
Rating.prototype.AddEval = function(async, val)
{
	this.serviceUri = _servicePrefix + "/rateditems/" + encodeURIComponent(this.contentSourceId) + "/" + this.itemId + "/" + this.ratingid + "/eval/" + val.toString();
	var msg = "xml=" + encodeURIComponent("<RatingEval>" + val + "</RatingEval>");
	this.Call("POST", msg, false);
	if(this.error.number > 0)return;
	if(!async)this.Load();
}
addMethod(Rating, "GetInstance", function(node){
  var o = new Rating();
  o.xmldoc = node;
  s.Deserialize(o, o.xmldoc);
});
addMethod(Rating, "GetInstance", function(contentSourceId, itemId, ratingid, rating, comment, positiveevals, totalevals, totalcomments, accountId, lobUserId, displayName, jobRole){
  var o = new Rating();
  o.contentSourceId = contentSourceId
  o.itemId = itemId;
  o.ratingid= ratingid;
  o.rating = rating;
  o.comment = comment;
  o.positiveevals = positiveevals;
  o.totalevals = totalevals;
  o.totalcomments = totalcomments;
  o.userAccount= UserAccount.GetInstance(accountId, lobUserId, displayName, jobRole);
  return o;
});
addMethod(Rating, "GetInstance", function(contentSourceId, itemId){
  var o = new Rating();
  o.contentSourceId = contentSourceId;
  o.itemId = itemId
  o.Fetch(false);
  return o;
});
addMethod(Rating, "GetInstance", function(contentSourceId, itemId, callback){
  var o = new Rating();
  o.contentSourceId = contentSourceId;
  o.itemId = itemId
  o.OnUpdate.push(callback);
  o.Fetch(true);
  return o;
});
addMethod(Rating, "GetInstance", function(contentSourceId, itemId, ratingid, rating, comment){
  var o = new Rating();
  o.contentSourceId = contentSourceId
  o.itemId = itemId;
  o.ratingid = ratingid;
  o.rating = rating;
  o.comment = comment;
  o.userAccount= UserAccount.GetInstance(0, '', '', '');
  return o;
});

function UserAccount()
{
	//[Type:UserAccount]
	//[Serializable:["accountId", "lobUserId", "displayName", "jobRole"]]
    this.accountId = 0;
    this.lobUserId = '';
    this.displayName = '';
    this.jobRole = '';
}
UserAccount.prototype = new Service;
UserAccount.prototype.constructor = UserAccount;
addMethod(UserAccount, "GetInstance", function(node){
  var o = new UserAccount();
  o.xmldoc = node;
  s.Deserialize(o, o.xmldoc);
  return o;
});
addMethod(UserAccount, "GetInstance", function(accountId, lobUserId, displayName, jobRole){
  var o = new UserAccount();
  o.accountId = accountId;
  o.lobUserId = lobUserId;
  o.displayName = displayName;
  o.jobRole = jobRole;
  return o;
});

function RatedItemCollection()
{
	//[Type:RatedItemCollection]
	//[Serializable:["ratedItems"]]
	this.ratedItems = new Array();
	this.ratedItems.Type = "RatedItem";
	this.contentSourceId = '';
	this.idList = '';
	this.ratedItemsHT = {};
	
	this.Load = function()
    {
		s.Deserialize(this, this.xmldoc);
		for(var i = 0; i < this.ratedItems.length; i++)
		{
			this.ratedItemsHT[this.ratedItems[i].itemId.toString()] = this.ratedItems[i];
		}	
    }
}
RatedItemCollection.prototype = new Service;
RatedItemCollection.prototype.constructor = RatedItemCollection;
RatedItemCollection.prototype.Fetch = function(async)
{
	this.serviceUri = _servicePrefix + "/rateditems/" + encodeURIComponent(this.contentSourceId) + "/?object=rateditem&itemids=" + this.idList;
	this.Call("GET", "", async);
	if(this.error.number > 0)return;
	if(!async)this.Load();
}
RatedItemCollection.prototype.AddItemId = function(id)
{
	if(this.idList != 0)
		this.idList += ','+id;
	else
		this.idList = id;
}
RatedItemCollection.prototype.AddItem = function(ratedItem)
{
	var l = this.ratedItems.length;
	this.ratedItems[l] = ratedItem;
	this.ratedItemsHT[this.ratedItems[l].itemId.toString()] = this.ratedItems[l];
}
RatedItemCollection.prototype.GetItem = function(itemId)
{
	return this.ratedItemsHT[itemId.toString()];
}
addMethod(RatedItemCollection, "GetInstance", function(contentSourceId, idList){
	var o = new RatedItemCollection();
  	o.contentSourceId = contentSourceId;
	o.idList = idList;
    o.Fetch(false);
	return o;
});
addMethod(RatedItemCollection, "GetInstance", function(contentSourceId, idList, callback){
	var o = new RatedItemCollection();
  	o.contentSourceId = contentSourceId;
	o.idList = idList;
	o.OnUpdate.push(callback);
    o.Fetch(true);
	return o;
});


function RatingCollection()
{
	//[Type:RatingCollection]
	//[Serializable:["ratings"]]
	this.ratings = [];
	this.ratings.Type = "Rating";
	this.contentSourceId = '';
	this.idList = '';
	this.ratingsHT = {};
	this.fetched = false;
	this.forUser = true;
	
	this.Load = function()
    {
		s.Deserialize(this, this.xmldoc);
		if(this.forUser)
		{
			for(var i = 0; i < this.ratings.length; i++)
			{
				this.ratingsHT[this.ratings[i].itemId] = this.ratings[i];
			}
		}
		else
		{
			for(var i = 0; i < this.ratings.length; i++)
			{
				this.ratingsHT[this.ratings[i].ratingid.toString()] = this.ratings[i];
			}
		}
		this.fetched = true;
    }
}
RatingCollection.prototype = new Service;
RatingCollection.prototype.constructor = RatingCollection;
RatingCollection.prototype.FetchAllForCurrentUser = function(async)
{
	this.serviceUri = _servicePrefix + "/rateditems/" + encodeURIComponent(this.contentSourceId) + "/?object=rating&itemids=" + this.idList;
	this.Call("GET", "", async);
	if(this.error.number > 0)return;
	if(!async)this.Load();
}
RatingCollection.prototype.FetchAllForItem = function(async)
{
	this.serviceUri = _servicePrefix + "/rateditems/" + encodeURIComponent(this.contentSourceId) + "/" + this.idList+ "/";
	this.Call("GET", "", async);
	if(this.error.number > 0)return;
	if(!async)this.Load();
}
RatingCollection.prototype.AddItemId = function(id)
{
	if(this.idList != 0)
		this.idList += ','+id;
	else
		this.idList = id;
}
RatingCollection.prototype.AddRating = function(rating)
{
	var l = this.ratings.length;
	this.ratings[l] = rating;
	if(this.forUser)
		this.ratingsHT[this.ratings[l].itemId] = this.ratings[l];		
	else
		this.ratingsHT[this.ratings[l].ratingid.toString()] = this.ratings[l];
}
RatingCollection.prototype.GetRating = function(id)
{
	if(!this.fetched)
		if(this.forUser)
			this.FetchAllForCurrentUser(false);
		else
			this.FetchAllForItem(false);
	return this.ratingsHT[id];
}
addMethod(RatingCollection, "GetInstance", function(contentSourceId, idList, forUser){
	var o = new RatingCollection();
  	o.contentSourceId = contentSourceId;
	o.idList = idList;
	o.forUser = forUser;
	if(forUser)
    	o.FetchAllForCurrentUser(false);
    else
    	o.FetchAllForItem(false);
    	
	return o;
});
addMethod(RatingCollection, "GetInstance", function(contentSourceId, idList, forUser, callback){
	var o = new RatingCollection();
  	o.contentSourceId = contentSourceId;
	o.idList = idList;
	o.forUser = forUser;
	o.OnUpdate.push(callback);
	if(forUser)
    	o.FetchAllForCurrentUser(true);
    else
    	o.FetchAllForItem(true);
    	
	return o;
});
addMethod(RatingCollection, "GetInstance", function(xml, forUser){
	var o = new RatingCollection();
	o.forUser = forUser;
	var doc = new ActiveXObject("MSXML2.DOMDocument");
    doc.loadXML(xml);
    o.xmldoc = doc.documentElement
	o.Load();
	return o;
});

/******************************************************************************
End Core rating objects
******************************************************************************/

// =========== Common ===================================

function sortDropDownList(id) 
{	
    var obj = document.getElementById(id);
    var values = new Array();
    var hashtable = new Object();
    var selectedValue = null;
    
    for(var i = 0; i < obj.options.length; i++)
   	{
    	if (obj.options[i].selected)
    		selectedValue = obj.options[i].value;
    	values.push(obj.options[i].innerHTML);
    	hashtable[obj.options[i].innerHTML] = obj.options[i].value;
    }	
	    	
    values = values.sort();
    for(var j = 0; j < values.length; j++) 
    {
        obj.options[j].innerHTML = values[j];
        obj.options[j].value = hashtable[values[j]];
        if (values[j] == selectedValue)
        	obj.options[j].selected = true;
    }
}

function uiGetAbsoluteX(eltIn)
{
	if (eltIn.offsetParent == null)
		return eltIn.offsetLeft;
	else
		return eltIn.offsetLeft + uiGetAbsoluteX(eltIn.offsetParent);
}

function uiGetAbsoluteY(eltIn)
{
	if (eltIn.offsetParent == null)
		return eltIn.offsetTop;
	else
		return eltIn.offsetTop + uiGetAbsoluteY(eltIn.offsetParent);
}

function addOption(selectbox,text,value )
{
    var optn = document.createElement("OPTION");
    optn.text = text;
    optn.value = value;
    selectbox.options.add(optn);
}

function removeSelectedOptions(selectbox)
{
    var i;
    for(i=selectbox.options.length-1;i>=0;i--)
    {
        if(selectbox.options[i].selected)
        selectbox.remove(i);
    }
}

function XmlXsltTransform(xmlString,xsltString)
{
	xmlString = decodeURIComponent(xmlString);
	xsltString = decodeURIComponent(xsltString);
	
	//_rc = RatingCollection.GetInstance(xmlString);
	var xmlDoc = new ActiveXObject("MSXML2.DOMDocument");
    xmlDoc.loadXML(xmlString);
	var xsltDoc = new ActiveXObject("MSXML2.DOMDocument");
    xsltDoc.loadXML(xsltString);

	var transform = null
	try
	{
		transform =  xmlDoc.transformNode(xsltDoc);
	}
	catch(e)
	{
		return e.description;
	}	
	return	transform;
}

function AddStyleSheetReference(styleSheetHref)
{
	var ns = document.createElement('link');
	ns.setAttribute('type', 'text/css');
	ns.setAttribute('id', 'RatingCss');
	ns.setAttribute('rel', 'stylesheet');
	document.getElementsByTagName('head')[0].appendChild(ns);
	document.getElementById('RatingCss').href = styleSheetHref;
}

var qsParm = null;
function computeQueryString()
{
	qsParm = new Array();
    var query = window.location.search.substring(1);
    var parms = query.split('&');
    for (var i=0; i<parms.length; i++) 
    {
       var pos = parms[i].indexOf('=');
       if (pos > 0) 
       {
          var key = parms[i].substring(0,pos);
          var val = parms[i].substring(pos+1);
          qsParm[key] = URLDecode(val);
      }
   }
}

function applyConfigOnRatingControl(ratedItem)
{
	var aveRating = computeRoundedAverageRating(ratedItem.averageRating);
    renderRatingsImagesById(ratedItem.controlPrefix + _idAddOnImageRatings, aveRating*2 , "rated");
	applyControlMasking(ratedItem.controlPrefix);
}

function LowerCaseFirstCharacter(mystring)
{
	return mystring.substring(0,1).toLowerCase()+ mystring.substring(1,mystring.length);
}