﻿
Type.registerNamespace("PlainJoeStudios.Web.Controls");PlainJoeStudios.Web.Controls.TimeSynchronization=function(args){this.Ctor(args);};PlainJoeStudios.Web.Controls.TimeSynchronization.prototype={TCL_AJAX_TIMEOUT:3000,DEFAULT_NUM_TESTS_TO_PERFORM:10,INITIAL_DATA_ASSUMED_DELAY:250,TEST_URL:"/PlainJoeStudios.Web/Handlers/LatencyTest.ashx",_bIsRunningTest:false,_iNumTestsRunning:0,_tcl_nTestCounter:null,_tcl_results_clockOffsetsAdjusted:null,_tcl_results_roundTripLatencies:null,_iSyncDelta:0,_arr_TestCompleteListeners:null,Ctor:function(args){if(window.g_TimeSynchronization){return;}
var This=this;this._arr_TestCompleteListeners=[];var iClientTime=new Date().getTime();var iServerTime=new Date(args["ServerTime"]).getTime()+(this.INITIAL_DATA_ASSUMED_DELAY/2);this._iSyncDelta=iClientTime-iServerTime;;window.g_TimeSynchronization=this;},getServerTime:function(oClientTime){if(oClientTime==null){return this.getServerTime(new Date());}
if(typeof(oClientTime)==="number"){return oClientTime-this._iSyncDelta;}
else{return new Date(oClientTime.getTime()-this._iSyncDelta);}},getClientTime:function(oServerTime){if(typeof(oServerTime)==="number"){return oServerTime+this._iSyncDelta;}
else{return new Date(oServerTime.getTime()+this._iSyncDelta);}},RegisterTestCompleteListener:function(fnListener){if(typeof(fnListener)!=="function"){return;}
this._arr_TestCompleteListeners.push(fnListener);},CalculateSynchronization:function(iNumTests){if(this._bIsRunningTest){return;}
this._iNumTestsRunning=iNumTests||this.DEFAULT_NUM_TESTS_TO_PERFORM;this._bIsRunningTest=true;this._tcl_BeginCascade(null);},_tcl_TestsComplete:function(){var iDeltaAvg=this._getMedian(this._tcl_results_clockOffsetsAdjusted);this._iSyncDelta=iDeltaAvg;for(var i=0;i<this._arr_TestCompleteListeners.length;++i){this._arr_TestCompleteListeners[i](this._iSyncDelta);}
this._bIsRunningTest=false;},_tcl_BeginCascade:function(onFinish){this._tcl_nTestCounter=0;this._tcl_results_clockOffsetsAdjusted=[];this._tcl_results_roundTripLatencies=[];this._tcl_currentStartTimeClient=null;this._tcl_currentEndTimeClient=null;this._tcl_currentTimeServer=null;this._tcl_onFinish=onFinish;this._tcl_Cascade();},_tcl_Cascade:function(){var This=this;if(this._tcl_nTestCounter>=this._iNumTestsRunning){this._tcl_TestsComplete();return;}
jQuery.ajax({cache:false,beforeSend:function(){This._tcl_AjaxBeforeSend();},success:function(p1,p2){This._tcl_AjaxSuccess(p1,p2);},error:function(){This._tcl_AjaxFail();},dataType:"text",url:This.TEST_URL,type:"GET"});},_tcl_AjaxBeforeSend:function(){this._tcl_currentStartTimeClient=new Date();},_tcl_AjaxSuccess:function(data,status){var iClientTimeReported=new Date().getTime();var iServerTimeReported=new Date(data).getTime();var iRoundTripLatency=iClientTimeReported-this._tcl_currentStartTimeClient.getTime();var iAdjustedServerTime=iServerTimeReported+iRoundTripLatency/2;var iDelta=iClientTimeReported-iAdjustedServerTime;this._tcl_results_clockOffsetsAdjusted[this._tcl_nTestCounter]=iDelta;this._tcl_results_roundTripLatencies[this._tcl_nTestCounter]=iRoundTripLatency;++this._tcl_nTestCounter;this._tcl_Cascade();},_tcl_AjaxFail:function(){this._tcl_results_clockOffsetsAdjusted[this._tcl_nTestCounter]=null;this._tcl_results_roundTripLatencies[this._tcl_nTestCounter]=null;++this._tcl_nTestCounter;this._tcl_Cascade();},_getMedian:function(arr){var iLen=arr.length;var arr_oSorted=[];for(var i=0;i<iLen;++i){arr_oSorted[i]=arr[i];}
arr_oSorted.sort(function(a,b){return a-b;});arr=arr_oSorted;if(iLen===0){return Number.NaN}
if(iLen===1){return arr[0];}
if(iLen===2){return(arr[0]+arr[1])/2;}
if(iLen%2===1){var iHalf=(iLen-1)/2;return arr[iHalf];}
else{var iHalf=(iLen/2)-1;return(arr[iHalf]+arr[iHalf+1])/2;}}};