
// helper functions ----------------------------------------------
function Utilities() {
	this.dumpResponseXML= function(responseXML)
	{
	    // doesn't work on IE.  Joy.
	    var string = (new XMLSerializer()).serializeToString(responseXML);
	    alert(string);
	};

	this.CreateXMLRequestObject= function()
	{
	    var req;
	    
	    // branch for native XMLHttpRequest object
	    if(window.XMLHttpRequest) {
	        try {
	            req = new XMLHttpRequest();
	        } catch(e) {
	            req = false;
	        }
	        // branch for IE/Windows ActiveX version
	    } else if(window.ActiveXObject) {
	        try {
	            req = new ActiveXObject("Msxml2.XMLHTTP");
	        } catch(ex) {
	            try {
	                req = new ActiveXObject("Microsoft.XMLHTTP");
	            } catch(ex2) {
	                req = false;
	            }
	        }
	    }
	    
	    return req;
	};
	
	this.getCookie= function(Name) { 
		var re=new RegExp(Name+"=[^;]+", "i"); //construct RE to search for target name/value pair
		if (document.cookie.match(re)) {//if cookie found
			return document.cookie.match(re)[0].split("=")[1]; //return its value
		}
		return null;
	};

	this.setCookie= function(name, value, days) {
		var expires= "";
		if(days) {
			var date= new Date();
			date.setTime(date.getTime()+(days*24*60*60*1000));
			expires= "; expires="+date.toGMTString();
		}
		document.cookie = name+"="+value+expires; // +"; path=/";
	};
	
	this.clearCookie= function(name) {
		this.setCookie(name, "", -1);
	};
	
	this.BuildPageIndexer= function(
		sortContainer,
		firstItem,
		itemsPerPage,
		totalItems,
		nextFunction,
		prevFunction,
		gotoFunction,
		userData)
	{
		var pageSections= 3;
		var pageIndex= Math.floor(firstItem/itemsPerPage)+1;
		var pageCount= Math.floor(totalItems/itemsPerPage) + ((totalItems%itemsPerPage)?1:0);
		var startIndex= Math.max(pageIndex-1, 1);
		var endIndex= Math.min(startIndex+pageSections-1, pageCount);
	
	//alert("First:"+firstItem+ " IPP: "+itemsPerPage+" Total: "+totalItems+" Start: "+startIndex+" End: "+endIndex+" Page Index: "+pageIndex);
//		var sortContainer= $(containerDiv);
		
		sortContainer.empty();
		if(startIndex+1 >= pageSections)
		{
			$("<li>1</li>").appendTo(sortContainer);
			$("<li>...</li>").appendTo(sortContainer);
		}
	
		for(var ii= startIndex; ii<=endIndex; ii++) {
			if(ii==pageIndex)
			{
				$('<li class="active">'+ii+'</li>').appendTo(sortContainer);
			} else {
				$("<li>"+ii+"</li>").appendTo(sortContainer);
			}
		}
			
		if(endIndex<pageCount-1) {
			$("<li>...</li>").appendTo(sortContainer);
			$("<li>"+pageCount+"</li>").appendTo(sortContainer);
		} else if(endIndex==pageCount-1) {
			$("<li>"+pageCount+"</li>").appendTo(sortContainer);
		}
		
		if(pageIndex>1) {
			$('<li class="prev"></li>').appendTo(sortContainer);
		}
		if(pageIndex<pageCount) {
			$('<li class="next"></li>').appendTo(sortContainer);
		}
	
		sortContainer.children("li").bind("click", 
			function(e) {
				var page= $(this).text();
	//alert("page: " +page);
				if($(this).hasClass('prev')) {
					prevFunction(userData);
				} else if($(this).hasClass('next')) {
					nextFunction(userData);
				} else if(page != '...') {
					page= parseInt(page, 10);
					gotoFunction(userData, page);
				}
			}
		);
	};
}

// Utilities global...
var Utilities= new Utilities();

/* object oriented javascript (is cool) */
function WebService(
	settings)
{
	this.ServerURL= settings.contentURL;
    this.PendingCalls= [];
    this.CompanyCode= settings.companyCode;
    this.SessionIdentifier= String((new Date()).getTime()).replace(/\D/gi,''); 
	this.PID= settings.PID;
    this.Token= null;
    this.IncludeSortFields= settings.includeSortFields;
    this.IncludeSeriesFields= settings.includeSeriesFields;
    this.Formats= settings.feedFormats; // can be changed if you want MP3

    if(document.URL.substr(0, 8)=="https://")
    {
        this.ServerURL= this.ServerURL.replace(/http/i, "https");
    }

	this.xmlhttp= Utilities.CreateXMLRequestObject();
    
    
    this.MakeNextCall= function() {
	    this.PendingCalls.shift();
	    
	    // run the next one..
	    if(this.PendingCalls.length>0)
	    {
	        this.PendingCalls[0].Run(this);
	    }
    };
    
    this.QueueCall= function(call) {
    	this.PendingCalls.push(call);
	    if(this.PendingCalls.length==1)
    	{
        	// none running; let's run this one.
	        call.Run(this);
    	}
    };
    
    this.QueueREST= function(url, parseProc, completionProc, userdata) { // completionProc(statusCode, xml, userdata)
    	var call= new WebServiceCall(this, "", "", parseProc, completionProc, userdata);
    	call.ChangeToGet(url);
    	
    	this.QueueCall(call);
    };

    this.QueueJSON= function(url, parseProc, completionProc, userdata) { // completionProc(statusCode, json, userdata)   	
    	var call= new WebServiceCall(this, "", "", parseProc, completionProc, userdata);
    	call.ChangeToGet(url);
    	call.SetAsJSON();
    	
    	this.QueueCall(call);
    };
    
    this.Authenticated= function() {
    	return (this.Token!=null);
    };

	this.LoadTeasers= function(completionProc, userData) {
    	this.QueueJSON(this.ServerURL+
    		'/getTeaserImages'+
    		'?pid='+this.PID,
    		function(jsonResponse) {
    			return jsonResponse;
    		},
    		completionProc, userData);
	};
    
	this.StartVideo= function(assetID, completionProc, userData) {
    	this.QueueJSON(this.ServerURL+
    		'/startVideo'+
    		'?token='+this.Token+
    		'&asset='+assetID,
    		function(jsonResponse) {
    			return jsonResponse;
    		},
    		completionProc, userData);
	};

	this.PlayVideo= function(assetID, completionProc, userData) {
    	this.QueueJSON(this.ServerURL+
    		'/playVideo'+
    		'?token='+this.Token+
    		'&asset='+assetID,
    		function(jsonResponse) {
    			return jsonResponse;
    		},
    		completionProc, userData);
	};

	this.PauseVideo= function(assetID, completionProc, userData) {
    	this.QueueJSON(this.ServerURL+
    		'/pauseVideo'+
    		'?token='+this.Token+
    		'&asset='+assetID,
    		function(xmlResponse) {
    			return null;
    		},
    		completionProc, userData);
	};

	this.EndVideo= function(assetID, completionProc, userData) {
    	this.QueueJSON(this.ServerURL+
    		'/endVideo'+
    		'?token='+this.Token+
    		'&asset='+assetID,
    		function(xmlResponse) {
    			return null;
    		},
    		completionProc, userData);
	};
	
	this.GetCategoryReleaseList= function(startIndex, endIndex, category, completionProc, userData) {
		var searchQuery= "&query=Categories|"+escape(category);
		this.GetReleaseList(startIndex, endIndex, searchQuery, completionProc, userData);
	};

	this.GetSearchReleaseList= function(startIndex, endIndex, searchText, completionProc, userData) {
    	var searchQuery= "&query=CommonSearch|"+escape(searchText);
		this.GetReleaseList(startIndex, endIndex, searchQuery, completionProc, userData);
	};

	this.GetSingleEpisodeReleaseList= function(startIndex, endIndex, showCode, completionProc, userData) {
    	var searchQuery= "&query=ShowCode|"+escape(showCode);
		this.GetReleaseList(startIndex, endIndex, searchQuery, completionProc, userData);
	};

	this.GetReleaseList= function(startIndex, endIndex, searchQuery, completionProc, userData) {
	    var url= this.ServerURL+'/getReleaseList?PID='+this.PID+
		    '&field=author&field=description&field=longDescription&field=format&'+
		    'field=length&field=thumbnailURL&field=title&field=URL&field=EpisodeCode'+
		    ((this.IncludeSortFields)?'&field=airdate&field=stars&field=avg-stars&field=avg-stars-count&field=favorite&field=sort-field':'')+
		    ((this.IncludeSeriesFields)?'&field=series&field=series_thumbnail':'')+
		    '&startIndex='+startIndex+
		    '&endIndex='+endIndex+searchQuery;
		    //+'&query=Formats|'+this.Formats;
	    var parts= this.Formats.split(',');
	    for(var ii= 0; ii<parts.length; ii++) {
	    	url+= '&query=Formats|'+parts[ii];
	    }
	   
	    if(this.Token != null) {
	    	url+= '&token='+this.Token;
	    }

		this.QueueJSON(url, function(jsonResponse) {
		 return jsonResponse; }, completionProc, userData);

	};

	this.GetCategoryList= function(completionProc, userData) {
		var url= this.ServerURL+'/getCategoryList?PID='+this.PID+
		'&query=hasreleases'+
		'&query=includeparents&field=depth&field=title&'+
		'field=ID&field=parentID&field=fullTitle';

	    if(this.Token != null) {
	    	url+= '&token='+this.Token;
	    }

		this.QueueJSON(url, function(jsonResponse) {
		 return jsonResponse; }, completionProc, userData);
	};
	
	this.Authenticate= function(username, password, completionProc, userData) {
		var url= this.ServerURL+'/authenticate?u='+username+
			'&pw='+password+'&cc='+this.CompanyCode+
			'&session='+this.SessionIdentifier;
		var ws= this;
		this.QueueJSON(url, 
			function(jsonResponse) {
				if(jsonResponse.valid)
				{ 
					ws.Token= jsonResponse.token; 
					ws.CustomerName= jsonResponse.customerName;
					ws.CustomerEmail= jsonResponse.customerEmail;
				}
				return jsonResponse; 
			},
			completionProc, userData);
	};
	
	this.OEMAuthenticate= function(query_string, completionProc, userData) {
		var url= this.ServerURL+'/oemauthenticate?q='+encodeURIComponent(query_string)+
			'&cc='+this.CompanyCode+
			'&session='+this.SessionIdentifier;
		var ws= this;
		this.QueueJSON(url, 
			function(jsonResponse) {
				if(jsonResponse.valid)
				{ 
					ws.Token= jsonResponse.token; 
					ws.CustomerName= jsonResponse.customerName;
					ws.CustomerEmail= jsonResponse.customerEmail;
				}
				return jsonResponse; 
			},
			completionProc, userData);	
	};

	this.SCORMAuthenticate= function(orgId, studentId, courseCode, scoId, CBIcourseCode, CBIscoId, completionProc, userData) {
		var url= this.ServerURL+'/scormauthenticate?orgId='+orgId+
			'&studentid='+studentId+
			'&courseCode='+courseCode+
			'&scoId='+scoId+
			'&cc='+this.CompanyCode+
			'&cbiScoId='+CBIscoId+
			'&cbiCourseCode='+CBIcourseCode+
			'&session='+this.SessionIdentifier+
			'&referrer='+encodeURIComponent(document.referrer);

		var ws= this;
		this.QueueJSON(url, 
			function(jsonResponse) {
				if(jsonResponse.valid)
				{ 
					ws.Token= jsonResponse.token; 
					ws.CustomerName= jsonResponse.customerName;
					ws.CustomerEmail= jsonResponse.customerEmail;
				}
				return jsonResponse; 
			},
			completionProc, userData);	
	};
	
	this.UserReviews= function(showCode, startIndex, endIndex, completionProc, userData) {
		var url= this.ServerURL+'/customerReviews?'+
			'cc='+this.CompanyCode+'&'+
			'showCode='+showCode+'&'+
			'startIndex='+startIndex+'&'+
			'endIndex='+endIndex;
		this.QueueJSON(url, 
			function(jsonResponse) {
				return jsonResponse;
			},
			completionProc, userData);
	};
	
	this.Review= function(showCode, rating, title, body, completionProc, userData) {
		if(this.Authenticated())
		{
			var url= this.ServerURL+'/addCustomerReview?'+
				'token='+this.Token+'&'+
				'showCode='+showCode+'&'+
				'rating='+rating+'&'+
				'title='+title+'&'+
				'comment='+body;
			this.QueueJSON(url, 
				function(jsonResponse) {
					return jsonResponse;
				},
				completionProc, userData);
		}
	};

	/* Favorites */
	this.AddToFavorites= function(showCode, completionProc, userData) {
		this.AddOrRemoveFromFavorites('add', showCode, completionProc, userData);
	};
	
	this.RemoveFromFavorites= function(showCode, completionProc, userData) {
		this.AddOrRemoveFromFavorites('del', showCode, completionProc, userData);
	};

	this.AddOrRemoveFromFavorites= function(verb, showCode, completionProc, userData) {
		if(this.Authenticated())
		{
			var url= this.ServerURL+'/favorites?'+
				'token='+this.Token+'&'+
				'verb='+verb+'&'+
				'showCode='+showCode;
			this.QueueJSON(url, 
				function(jsonResponse) {
					return jsonResponse;
				},
				completionProc, userData);
		}
	};
	
	/* Discussion boards */
	this.ListTopics= function(showCode, start, count, completionProc, userData) {
		var url= this.ServerURL+'/listTopics'+
			'?cc='+this.CompanyCode+
			'&showCode='+showCode+
			'&start='+start+
			'&count='+count;
	    if(this.Token != null) {
	    	url+= '&token='+this.Token;
	    }

		this.QueueJSON(url, 
			function(jsonResponse) {
				return jsonResponse; 
			},
			completionProc, userData);
	};

	this.ListPosts= function(topic_id, parent_post_id, initialView, start, count, completionProc, userData) {
		var url= this.ServerURL+'/listPosts'+
			'?cc='+this.CompanyCode+
			'&topic_id='+topic_id+
			'&initialView='+initialView+
			'&start='+start+
			'&count='+count;
	    if(this.Token != null) {
	    	url+= '&token='+this.Token;
	    }
	    if(parent_post_id != null) {
	    	url+= '&parent_post_id='+parent_post_id;
	    }

		this.QueueJSON(url, 
			function(jsonResponse) {
				return jsonResponse; 
			},
			completionProc, userData);
	};

	this.CreateTopic= function(showCode, title, post, isSpoiler, completionProc, userData) {
		var url= this.ServerURL+'/createTopic'+
			'?token='+this.Token+
			'&showCode='+showCode+
			'&title='+title+
			'&post='+post+
			'&spoiler='+isSpoiler;
		this.QueueJSON(url, 
			function(jsonResponse) {
				return jsonResponse; 
			},
			completionProc, userData);
	};
	
	this.PostToTopic= function(topic_id, post, isSpoiler, completionProc, userData) {
		var url= this.ServerURL+'/postToTopic'+
			'?token='+this.Token+
			'&topic_id='+topic_id+
			'&post='+post+
			'&spoiler='+isSpoiler;
		this.QueueJSON(url, 
			function(jsonResponse) {
				return jsonResponse; 
			},
			completionProc, userData);
	};

	this.PostToPost= function(topic_id, post_id, post, isSpoiler, completionProc, userData) {
		var url= this.ServerURL+'/postToPost'+
			'?token='+this.Token+
			'&topic_id='+topic_id+
			'&post_id='+post_id+
			'&post='+post+
			'&spoiler='+isSpoiler;
		this.QueueJSON(url, 
			function(jsonResponse) {
				return jsonResponse; 
			},
			completionProc, userData);
	};
	
	this.MarkTopicPost= function(showCode, topic_id, post_id, verb, completionProc, userData) {
		var url= this.ServerURL+'/markTopicPost'+
			'?token='+this.Token+
			'&showCode='+showCode+
			'&topic_id='+topic_id+
			'&post_id='+post_id+
			'&markType='+verb;
		this.QueueJSON(url, 
			function(jsonResponse) {
				return jsonResponse; 
			},
			completionProc, userData);
	};
	
	/* Logout */
	this.Logout= function(completionProc, userData) {
		var url= this.ServerURL+'/logout?token='+this.Token;
		var ws= this;
		this.QueueJSON(url, 
			function(jsonResponse) {
				ws.Token= null;
				return jsonResponse; 
			},
			completionProc, userData);
	};
	
    this.Whack= function(completionProc, userData) {
    	var url= "http://feeds.splashmedia.com/ps/JSON/PortalService/1.8/getReleaseList?"+
    		"PID=7oyJ02i9oP5SkqcUTTkrE8qvXVUqjNEX&field=title&field=customData&query=Formats|FLV";
    	
    	this.QueueJSON(url, function(jsonResponse) { return jsonResponse; }, completionProc, userData);
    };

    return this;
}


/* ----------- WebService Call object */
function WebServiceCall(
	ws, // webservice
	soapAction, 
	soapRequest, 
	parseResult, 
	completionProc, 
	userData)
{
    this.Verb= "POST";
    this.URL= ws.ServerURL; // bogus.
    this.SoapAction= soapAction;
    this.SoapRequest= soapRequest;
    this.ParseResult= parseResult;
    this.CompletionProc= completionProc;
    this.UserData= userData;
    this.IsJSON= false;
    this.Run= function(webservice) {
	    var call= this; // this is xmlhttp once it gets into the function, below.
	    
	    webservice.xmlhttp.open(this.Verb, this.URL, true);
	    webservice.xmlhttp.onreadystatechange= function() 
	    {
	        var result= null;
	        
	        switch(webservice.xmlhttp.readyState)
	        {
	            case 4:
	                if(webservice.xmlhttp.status==200)
	                {
//						$('div.debug').html($('div.debug').html()+'<p>');

	                    if(call.ParseResult != null)
	                    {
//							var start = (new Date).getTime();
	                    	if(call.IsJSON)
	                    	{
//								alert(webservice.xmlhttp.responseText);
	    	                    result= call.ParseResult(call.parseJSON(webservice.xmlhttp.responseText));
	                    	} else {
		                    	var dom= webservice.xmlhttp.responseXML;
		                        // getting a smil file results in text, not xml.  try to parse it.
		                        if(dom==null) {
		                        	dom= (new DOMParser()).parseFromString(webservice.xmlhttp.responseText, "text/xml");
		                        }
	    	                    result= call.ParseResult(dom);
	    	                }
//							var diff = (new Date).getTime() - start;
//							$('div.debug').html($('div.debug').html()+'URL: '+call.URL+'<br/>Parsing: '+diff+'<br/>');
	                    }
	                } else {
	                	alert("Call to "+call.URL+" returned status of "+webservice.xmlhttp.status);
	                }
	                
	                if(call.CompletionProc != null) {
//						var start = (new Date).getTime();
		                if(call.UserData != null)
		                {
//alert("Calling completion proc with status"+webservice.xmlhttp.status+" result: "+result+" userData: "+call.UserData+" URL: "+call.URL);
/* Run a test. */

		                    call.CompletionProc(webservice.xmlhttp.status, result, call.UserData);
		                } else {
		                    call.CompletionProc(webservice.xmlhttp.status, result);
		                }
//						var diff = (new Date).getTime() - start;
//						$('div.debug').html($('div.debug').html()+'CompletionProc: '+diff+'<br/>');
	                }
//					$('div.debug').html($('div.debug').html()+'</p>');
	                webservice.MakeNextCall();
	                break;
	                
	           case 3:
	                break;
			
	           default:
	                break;
	        }
	    };
	    
	    if(this.SoapAction != null)
	    {
	        webservice.xmlhttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
	        webservice.xmlhttp.setRequestHeader("SOAPAction", this.SoapAction);    
	    }
    	webservice.xmlhttp.send(this.SoapRequest);	
    };
    
	this.ChangeToGet= function(url) {
		this.Verb= "GET";
		this.SoapAction= null;
		this.SoapRequest= '';
		this.URL= url;
	};

	this.SetAsJSON= function() {
		this.IsJSON= true;
//		this.ParseResult= this.parseJSON; 
	};

   	this.parseJSON= function(text) {
		var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
			text.replace(/"(\\.|[^"\\])*"/g, ''))) &&
			eval('(' + text + ')');

		return my_JSON_object;
	};

    return this;
}

