/*!
 * This file is a part of Mibew Messenger.
 *
 * Copyright 2005-2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
!function(t,e,i,n){t.Server=function(t){this.updateTimer=null,this.options=n.extend({url:"",requestsFrequency:2,reconnectPause:1,onTimeout:function(){},onTransportError:function(){},onCallError:function(t){},onUpdateError:function(t){},onResponseError:function(t){}},t),this.callbacks={},this.callPeriodically={},this.callPeriodicallyLastId=0,this.ajaxRequest=null,this.buffer=[],this.functions={},this.functionsLastId=0,this.mibewAPI=new e(new this.options.interactionType)},t.Server.prototype.callFunctions=function(t,e,i){try{if(!(t instanceof Array))throw new Error("The first arguments must be an array");for(var n=0;n<t.length;n++)this.mibewAPI.checkFunction(t[n],!1);var r=this.generateToken();this.callbacks[r]=e,this.buffer.push({token:r,functions:t}),i&&this.update()}catch(s){return this.options.onCallError(s),!1}return!0},t.Server.prototype.callFunctionsPeriodically=function(t,e){return this.callPeriodicallyLastId++,this.callPeriodically[this.callPeriodicallyLastId]={functionsListBuilder:t,callbackFunction:e},this.callPeriodicallyLastId},t.Server.prototype.stopCallFunctionsPeriodically=function(t){t in this.callPeriodically&&delete this.callPeriodically[t]},t.Server.prototype.generateToken=function(){var t;do t="wnd"+(new Date).getTime().toString()+Math.round(50*Math.random()).toString();while(t in this.callbacks);return t},t.Server.prototype.processRequest=function(t){var e=new MibewAPIExecutionContext,i=this.mibewAPI.getResultFunction(t.functions,this.callbacks.hasOwnProperty(t.token));if(null===i)for(var n in t.functions)t.functions.hasOwnProperty(n)&&(this.processFunction(t.functions[n],e),this.buffer.push(this.mibewAPI.buildResult(e.getResults(),t.token)));else this.callbacks.hasOwnProperty(t.token)&&(this.callbacks[t.token](i.arguments),delete this.callbacks[t.token])},t.Server.prototype.processFunction=function(t,e){if(this.functions.hasOwnProperty(t["function"])){var i=e.getArgumentsList(t),r={};for(var s in this.functions[t["function"]])this.functions[t["function"]].hasOwnProperty(s)&&(r=n.extend(r,this.functions[t["function"]][s](i)));e.storeFunctionResults(t,r)}},t.Server.prototype.sendRequests=function(t){var e=this;this.ajaxRequest=i.ajax({url:e.options.url,timeout:5e3,async:!0,cache:!1,type:"POST",dataType:"text",data:{data:this.mibewAPI.encodePackage(t)},success:n.bind(e.receiveResponse,e),error:n.bind(e.onError,e)})},t.Server.prototype.runUpdater=function(){this.update()},t.Server.prototype.updateAfter=function(t){this.updateTimer=setTimeout(n.bind(this.update,this),1e3*t)},t.Server.prototype.restartUpdater=function(){this.updateTimer&&clearTimeout(this.updateTimer),this.ajaxRequest&&this.ajaxRequest.abort(),this.updateAfter(this.options.reconnectPause)},t.Server.prototype.update=function(){this.updateTimer&&clearTimeout(this.updateTimer);for(var t in this.callPeriodically)this.callPeriodically.hasOwnProperty(t)&&this.callFunctions(this.callPeriodically[t].functionsListBuilder(),this.callPeriodically[t].callbackFunction);if(0==this.buffer.length)return void this.updateAfter(this.options.requestsFrequency);try{this.sendRequests(this.buffer),this.buffer=[]}catch(e){this.options.onUpdateError(e)}},t.Server.prototype.receiveResponse=function(t,e,i){""==t&&this.updateAfter(this.options.requestsFrequency);try{var n=this.mibewAPI.decodePackage(t);for(var r in n.requests)this.processRequest(n.requests[r])}catch(s){this.options.onResponseError(s)}finally{this.updateAfter(this.options.requestsFrequency)}},t.Server.prototype.registerFunction=function(t,e){return this.functionsLastId++,t in this.functions||(this.functions[t]={}),this.functions[t][this.functionsLastId]=e,this.functionsLastId},t.Server.prototype.unregisterFunction=function(t){for(var e in this.functions)this.functions.hasOwnProperty(e)&&(t in this.functions[e]&&delete this.functions[e][t],n.isEmpty(this.functions[e])&&delete this.functions[e])},t.Server.prototype.onError=function(t,e,i){"abort"!=e&&(this.restartUpdater(),"timeout"==e?this.options.onTimeout():"error"==e&&this.options.onTransportError())}}(Mibew,MibewAPI,$,_);