"use strict";

var NetworkProtocol = require("./NetworkProtocol.js"),
    Error = require("./Error.js"),
	Utility = require("./Utility.js"),
	Debug = require("./Debug.js");

var Condicio = require("condicio");

/**
 * @ignore
 * @class
 * 网络会话
 */
function Session(ws, ip, port , errorHandler, rendererID) {
	var _this = this;
	
    this.ws = ws;
	this.ip = ip;
	this.port = port;
	this.rendererID = rendererID;
	this.activeClose = false;
	
    this.callbackManager = new Object;
	this.networkCloseListener = [];
	
	ws.onmessage = function (ev) {
		var recvPack = new NetworkProtocol.Package;
		recvPack.fromString(ev.data);

		switch (recvPack.type) {
			case NetworkProtocol.PackageType.Response: {
				if (!Condicio.isUndefined(recvPack.body.callbackID)) {
					var result = recvPack.body.result;
					var error = null;
					if (recvPack.body.error) {
						error = Error.genError(recvPack.body.error);
					}
					var currentCallback = _this.callbackManager[recvPack.body.callbackID];

					if(Debug.interfaceDebug)
					{
						var endTime = new Date();
						if (!currentCallback.keep)
						{
							var interfaceName = currentCallback.interfaceName;
							var usedTime = endTime - currentCallback.beginTime;
							console.log(interfaceName + ":" + usedTime);
						}
					}

					currentCallback.callback(error, result);
					
					if (!Condicio.isUndefined(currentCallback)){
						if (!currentCallback.keep)
							delete _this.callbackManager[recvPack.body.callbackID];
					}
				}
				break;
			}
			case NetworkProtocol.PackageType.Error: {
				errorHandler(Error.genError(recvPack.body.error));
				break;
			}
			case NetworkProtocol.PackageType.Ping: {
				var pack = new NetworkProtocol.Package(NetworkProtocol.PackageType.Pong);
				_this.ws.send(pack.toString());
			}
		}
	}
	
	ws.onclose = function (ev) {
		for ( var i=0; i < _this.networkCloseListener.length; ++i){
			_this.networkCloseListener[i]();
		}
		
		if(!_this.activeClose){
			errorHandler(new Error.NetworkError("The network has been disconnected"));			
		}
	}
};

/**
 * 请求方法调用
 *
 * @param {UUID}   		objectID			标示请求的对象
 * @param {String} 		methodName   		请求的对象方法名
 * @param {Object} 		params       		调用方法传入的参数
 * @param {Function} 	params.callback		异步调用完成回调
 * @param {Error}       params.callback.err    	异步调用出错传出错误
 * @param {Object}		params.callback.result 	异步调用成功传出结果
 */
Session.prototype.request = function(objectID, methodName, params){
	var type = NetworkProtocol.PackageType.Request;
	
	var pack = new NetworkProtocol.Package(type, {
        objectID: objectID,
        methodName: methodName,
        params: params
    });

	this.ws.send(pack.toString());
};

/**
 * 关闭连接
 */
Session.prototype.close = function() {
	this.activeClose = true;
	this.ws.close();
};

/**
 * 增加回调
 * 

 * @param {String} 		callbackID				标示回调的ID
 * @param {Function} 	callback  				异步调用返回结果
 * @param {Error}       callback.err    		异步调用失败返回错误
 * @param {Object}		callback.result 		异步调用成功返回结果
 * @param {String} 		interfaceName			接口名称
 * @param {Boolean}     keep 					回调一次设置为false,回调有可能多次,设置为true,可多次时候依赖外部主动删除callback
 */
Session.prototype.registerCallback = function(callbackID, callback, interfaceName, keep) {

	this.callbackManager[callbackID] = {
		callback: callback,
		interfaceName: interfaceName,
		keep: keep || false,
	};
	if (Debug.interfaceDebug) {
		this.callbackManager[callbackID].beginTime = new Date();
	}
};

/**
 * 删除回调
 * 
 * @param {String} callbackID  标示回调的ID
 */
Session.prototype.unregisterCallback = function(callbackID) {
	delete this.callbackManager[callbackID];
};

/**
 * 用于检测网络在连接状况下因某种原因断开之后,同时去关闭加载图片请求
 *
 * @param {Function} listener
 */
Session.prototype.addNetworkCloseListener = function(listener){
	this.networkCloseListener.push(listener);
}

module.exports = Session;