// +---------------------------------------------------
// | 最顶层的父窗口
// +---------------------------------------------------
var G_Parent = null;
var __ajax_cache = true;

// 得到操作的控件
function client_external()
{
	return window.external.qlC;
}

// +---------------------------------------------------
// | 获取客户端操作控件
// +---------------------------------------------------
function client_core_interface()
{
	if (G_Parent == null)
		G_Parent = getParent(window);
	return G_Parent.client_external();
}

// /////////////////////////register debug
// key/////////////////////////////////////////
// constructor
function Keymap(bindings)
{
	this.map = {};
	if (bindings)
	{
		for (name in bindings)
			this.map[name.toLowerCase()] = bindings[name];
	}
}

// bind func to key
Keymap.prototype.bind = function(key, func)
{
	this.map[key.toLowerCase()] = func;
};

// unbind key
Keymap.prototype.unbind = function(key)
{
	delete this.map[key.toLowerCase()];
};

// install the keymap on specified html element
Keymap.prototype.install = function(element)
{
	var keymap = this;
	function handler(event)
	{
		return keymap.dispatch(event);
	}

	if (element.addEventListener)
	{
		element.addEventListener(
			"keydown", handler, false
		);
		element.addEventListener(
			"keypress", handler, false
		);
	}
	else if (element.attachEvent)
	{
		element.attachEvent(
			"onkeydown", handler
		);
		element.attachEvent(
			"onkeypress", handler
		);
	}
	else
	{
		element.onkeydown = element.onkeypress = handler;
	}
};

// function key
Keymap.keyCodeToFunctionkey = {
	8	: "backspace",
	9	: "tab",
	13	: "return",
	27	: "escape",
	32	: "space",
	33	: "pageup",
	34	: "pagedown",
	35	: "end",
	36	: "end",
	37	: "left",
	38	: "up",
	112	: "f1",
	113	: "f2",
	114	: "f3",
	115	: "f4",
	116	: "f5",
	117	: "f6",
	118	: "f7",
	119	: "f8",
	120	: "f9",
	121	: "f10",
	122	: "f11",
	123	: "f12",
	114	: "numlock",
	145	: "scrolllock"
};

// printable key
Keymap.keyCodeToPrintableChar = {
	48	: "0",
	49	: "1",
	50	: "2",
	51	: "3",
	52	: "4",
	53	: "5",
	54	: "6",
	55	: "7",
	56	: "8",
	57	: "9",
	59	: ";",
	61	: "=",
	65	: "a",
	66	: "b",
	67	: "c",
	68	: "d",
	69	: "e",
	70	: "f",
	71	: "g",
	72	: "h",
	73	: "i",
	74	: "j",
	75	: "k",
	76	: "l",
	77	: "m",
	78	: "n",
	79	: "o",
	80	: "p",
	81	: "q",
	82	: "r",
	83	: "s",
	84	: "t",
	85	: "u",
	86	: "v",
	87	: "w",
	88	: "x",
	89	: "y",
	90	: "z",
	107	: "+",
	109	: "-",
	110	: ".",
	188	: ",",
	190	: ".",
	191	: "/",
	192	: "`",
	219	: "[",
	220	: "\\",
	219	: "]",
	222	: "\""
};

// dispatch key events based on the keymap bindings
Keymap.prototype.dispatch = function(event)
{
	var e = event || window.event;

	var modifiers = "";
	var keyname = null;

	if (e.type == "keydown")
	{
		var code = e.keyCode;
		if (code == 16 || code == 17 || code == 18)
			return;

		keyname = Keymap.keyCodeToFunctionkey[code];

		if (!keyname && (e.altKey || e.ctrlKey))
			keyname = Keymap.keyCodeToPrintableChar[code];

		if (keyname)
		{
			if (e.altKey)
				modifiers += "alt_";
			if (e.ctrlKey)
				modifiers += "ctrl_";
			if (e.shiftKey)
				modifiers += "shift_";
		}
		else
			return;
	}
	else if (e.type == "keypress")
	{
		if (e.altKey || e.ctrlKey)
			return;

		if (e.charCode != undefined && e.charCode == 0)
			return;

		var code = e.charCode || e.keyCode;

		keyname = String.fromCharCode(code);

		var lowercse = keyname.toLowerCase();
		if (keyname != lowercse)
		{
			keyname = lowercse;
			modifiers = "shift_";
		}
	}
	var func = this.map[modifiers + keyname];
	if (!func)
		func = this.map["default"];

	if (func)
	{
		var target = e.target;
		if (!target)
			target = e.srcElement;

		func(
			target, modifiers + keyname, e
		);

		if (e.stopPropagation)
			e.stopPropagation();
		else
			e.cancelBubble = true;
		if (e.preventDefault)
			e.preventDefault();
		else
			e.returnValue = false;
		return false;
	}
};

function handlerReflash()
{
	window.location = window.location;
}

function handlerDebug()
{
	var strHref = window.location.href;
	var pageName = strHref.slice(strHref.lastIndexOf("/ ") + 1);	
	window.open(
		pageName, 'debug'
	);
}

keymap = new Keymap(
	{
		"ctrl_r"	: handlerReflash,
		"ctrl_left"	: handlerDebug
	}
);
keymap.install(document);

// /////////////////////////register debug
// key/////////////////////////////////////////

// +---------------------------------------------------
// | 获取最顶层父窗口
// +---------------------------------------------------
function getParent(win)
{
	if (typeof(win.opener) === 'undefined')
	{
		if (win.parent === win)
		{
			return win;
		}
		return getParent(win.parent);
	}
	return getParent(win.opener);
}

// +---------------------------------------------------
// | 获取系统登录账户信息
// +---------------------------------------------------
function getSysUser()
{
	// return ['zhanglj888', '', '8888'];
	var obj = client_core_interface(),
		ret = obj.r(
			'G_SYS_UserName', ''
		);
	try
	{
		return ret.split('\r\n');
	}
	finally
	{
		ret = null;
		obj = null;
	}
}

// +---------------------------------------------------
// | 跳转个股诊断
// +---------------------------------------------------
function gotoDiagnose(mrkCode, stockNo)
{
	var obj = client_core_interface();
	obj.r(
		'S_VIEW_GOTO', 'DIAG\r\nComm=(' + mrkCode + ',' + stockNo + ')'
	);
}

// +---------------------------------------------------
// | 跳转到邮件中心
// +---------------------------------------------------
function OpenMailCenter(param)
{
	var obj = client_core_interface();
	obj.r(
		'S_MSG_OPENMAINWND', param
	);
}

// +---------------------------------------------------
// | 跳转到邮件列表
// +---------------------------------------------------
function OpenMailList(url)
{
	var obj = client_core_interface();
	obj.r(
		'S_MSG_OPENMSGLISTWND', url
	);
}

// +---------------------------------------------------
// | 跳转到视图
// +---------------------------------------------------
function client_core_gotoview(viewName, viewParaObject)
{
	try
	{
		var obj = client_core_interface(),
			viewPara = '';
		if (viewParaObject !== null)
		{
			for (var prop in viewParaObject)
			{
				if (viewParaObject[prop].indexOf(',') > 0)
					viewPara += prop.toString() + '=(' + viewParaObject[prop] + '),';
				else
					viewPara += prop.toString() + '=' + viewParaObject[prop] + ',';
			}
		}
		if (viewPara.length > 0)
			viewPara = viewPara.substr(
				0, viewPara.length - 1
			);
		var sViewGotoPara = viewName + '\r\n' + viewPara;
		obj.r(
			'S_View_Goto', sViewGotoPara
		);
	}
	catch (e)
	{
		_trace('出错(GetStockData()):' + e.message);
	}
}

// +---------------------------------------------------
// | 获取客户端保存的字符串数据
// | 说明：只取从客户端读到数据的文本部分
// +---------------------------------------------------
function getClientData(keyName)
{
	var data = getClientDataWithTime(keyName);
	try
	{
		if (data === null)
		{
			return null;
		}
		if (typeof(data.dValue) === 'undefined')
		{
			return null;
		}
		return data.dValue;
	}
	finally
	{
		data = null;
	}
}

// +---------------------------------------------------
// | 获取客户端保存的数据对象
// | 说明：取到的数据是一个对象，其格式：{TimeStamp: Date, dValue: 保存的数据}
// +---------------------------------------------------
function getClientDataWithTime(keyName)
{
	if (typeof(client_data_load) === 'undefined')
	{
		return null;
	}
	return client_data_load(
		keyName, 0
	);
}

// +---------------------------------------------------
// | 加载客户端保存的数据对象
// +---------------------------------------------------
function client_data_load(keyName, regionType)
{
	try
	{
		var obj = client_core_interface(),
			stkData = obj.r(
				'S_Etc_LoadData', keyName + '\r\n' + regionType
			);
		if (stkData === null || stkData.length === 0)
		{
			return null;
		}

		// 查看附带的时间戳，时间戳的格式 YYYYMMDD HH:MM:SS
		var iPos = stkData.indexOf('\r\n');
		if (iPos <= 0)
		{
			return null;
		}
		var timeStamp = stkData.substring(
			0, iPos
		),
			pData = stkData.substring(
				iPos + 2, stkData.length
			);
		if (timeStamp.length != 17)
		{
			return null;
		}

		var rltObj = {};
		// 特别注意，javascript中，mm月份的定义为(0-11)，所以这里必须做 -1 操作
		rltObj.TimeStamp = new Date(
			timeStamp.substring(
				0, 4
			),
			timeStamp.substring(
				4, 6
			) - 1,
			timeStamp.substring(
				6, 8
			),
			timeStamp.substring(
				9, 11
			),
			timeStamp.substring(
				12, 14
			),
			timeStamp.substring(
				15, 17
			)
		);
		rltObj.dValue = pData.replace(
			/\n\n/g, '\r\n'
		);
		return rltObj;
	}
	catch (e)
	{
		_trace('出错(client_data_load()):' + e.message);
		return null;
	}
}

// +---------------------------------------------------
// | 保存字符串数据到客户端
// | 说明：返回大于0的值：成功，否则失败！
// | 第四个参数（保存数据区域）说明：0，个人区域；1，共享区域
// +---------------------------------------------------
function saveStr2Client(keyName, dataValue)
{
	var obj = {};
	try
	{
		obj = client_core_interface();
		return obj.r(
			'S_Etc_SaveData', keyName + '\r\n1\r\n' + dataValue.replace(
				/\r\n/g, '\n\n'
			) + '\r\n0'
		);
	}
	catch (e)
	{
		_trace('出错(client_data_save()):' + e.message);
		return '0' + e.message;
	}
	finally
	{
		obj = null;
	}
}

// ----------------------------------------------------
// 工具的方法
// ----------------------------------------------------
function getRequest()
{
	var xmlhttp = null;
	if (window.XMLHttpRequest)
	{
		// code for all new browsers
		xmlhttp = new XMLHttpRequest();
	}
	else if (window.ActiveXObject)
	{
		// code for IE5 and IE6
		xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
	}
	if (!xmlhttp)
	{
		throw 'request object initialize fail!';
	}
	try
	{
		return xmlhttp;
	}
	finally
	{
		xmlhttp = null;
	}
}

// +---------------------------------------------------
// | 动态网页ajax加载
// +---------------------------------------------------
function ajax_load(url, async, callback)
{
	var req = getRequest();
	var callURL = ajax_url_random(url);
	var callbackfn = callback;
	req.open(
		'GET', callURL, async
	);
	req.onreadystatechange = function()
	{
		if (req.readyState == 4)
		{
			if (req.status == 200)
			{
				callbackfn(req.responseText);
				req = null;
			}
		}
	};
	req.send(null);
	callURL = null;
	callbackfn = null;
	req = null;
}

// +---------------------------------------------------
// | ajax加载，并缓存到客户端
// +---------------------------------------------------
function ajax_load_cache(url, async, callback)
{
	var callbackfn = callback;
	var callURL = ajax_url_random(url);
	var cachedata = null;
	if (__ajax_cache)
	{
		cachedata = ajax_url_cache_get(url);
	}
	var req = getRequest();
	req.open(
		'GET', callURL, async
	);
	req.onreadystatechange = function()
	{
		if (req.readyState == 4)
		{
			if (req.status == 200)
			{
				if (__ajax_cache)
				{				
					ajax_url_cache_set(
						url, req.getResponseHeader('Last-Modified'), req.responseText
					);
				}
				callbackfn(req.responseText);
				req = null;
			}
			else if (req.status == 304)
			{			
				callbackfn(cachedata['text']);
				req = null;
			}
			else
			{
				callbackfn(null);
				req = null;
			}
		}
	};

	if (__ajax_cache)
	{
		req.setRequestHeader(
			'If-Modified-Since', cachedata === null ? 'Thu, 01 Jan 1970 00:00:00 GMT' : cachedata['expire']
		);
	}
	req.send(null);
	callURL = null;
	callbackfn = null;
	cachedata = null;
	req = null;
}

// +---------------------------------------------------
// | 静态文件缓存
// +---------------------------------------------------

function ajax_cache_enable()
{
	__ajax_cache = true;
}

function ajax_cache_disable()
{
	__ajax_cache = false;
}

function ajax_url_cache_key(url)
{
	var pos = url.lastIndexOf('/');
	var l_url = url.substr(pos + 1);

	pos = l_url.indexOf('.');
	if (pos > 0)
	{
		l_url = l_url.substr(
			0, pos
		);
	}
	try
	{
		return 'w_' + l_url;
	}
	finally
	{
		pos = null;
		l_url = null;
	}
}

function ajax_url_cache_get(url)
{
	var dataobj = {};
	var key = ajax_url_cache_key(url);
	var dvalue = getClientData(key);
	try
	{
		if (dvalue === null)
		{
			return null;
		}
		try
		{
			dataobj = eval('(' + dvalue + ')');
			return dataobj;
		}
		catch (e)
		{
			return null;
		}
	}
	finally
	{
		dvalue = null;
		key = null;
		dataobj = null;
	}
}

function ajax_url_cache_set(url, expire, text)
{
	var key = ajax_url_cache_key(url);
	var data = {};
	data.expire = expire;
	data.text = text;

	saveStr2Client(
		key, JSON.stringify(data)
	);
	data = null;
	key = null;
}

function ajax_url_random(url)
{
	if (__ajax_cache)
		return url;

	if (url.indexOf('?') > 0)
	{
		url += '&_rand=' + Math.random();
	}
	else
	{
		url += '?_rand=' + Math.random();
	}
	return url;
}

// date 时间字串 ;separator 分隔符;
function get_date_yyyymmdd(date, separator)
{
	if (typeof(date) != 'object')
		date = new date();

	var year = '' + date.getFullYear();
	var month = '' + (100 + date.getMonth() + 1);
	var day = '' + (100 + date.getDate());

	return year + separator + month.substr(
		1, 2
	) + separator + day.substr(
		1, 2
	);
}

// +---------------------------------------------------
// |传入时间加上interval相应number数
// +---------------------------------------------------
function DateAdd(interval, number, date)
{
	switch (interval.toLowerCase())
	{
		case 'y' :
			return new Date(date.setFullYear(date.getFullYear() + number));// 年
		case 'm' :
			return new Date(date.setMonth(date.getMonth() + number));// 月
		case 'd' :
			return new Date(date.setDate(date.getDate() + number));// 日
		case 'w' :
			return new Date(date.setDate(date.getDate() + 7 * number));// 周
		case 'h' :
			return new Date(date.setHours(date.getHours() + number));// 时
		case 'n' :
			return new Date(date.setMinutes(date.getMinutes() + number));// 分
		case 's' :
			return new Date(date.setSeconds(date.getSeconds() + number));// 秒
		case 'l' :
			return new Date(date.setMilliseconds(date.getMilliseconds() + number));// 毫秒
	}
}

// +---------------------------------------------------
// |比较时间interval相应差值
// +---------------------------------------------------
function DateDiff(interval, date1, date2)
{
	var longMS = date2.getTime() - date1.getTime(); // 相差毫秒
	switch (interval.toLowerCase())
	{
		case 'y' :
			return parseInt(date2.getFullYear() - date1.getFullYear());
		case 'm' :
			return parseInt((date2.getFullYear() - date1.getFullYear()) * 12 + (date2.getMonth() - date1.getMonth()));
		case 'd' :
			var d1 = new Date(date1.getFullYear() + '/' + (date1.getMonth() + 1) + '/' + date1.getDate()),
				d2 = new Date(date2.getFullYear() + '/' + (date2.getMonth() + 1) + '/' + date2.getDate());
			return (d2 - d1) / 1000 / 60 / 60 / 24;
			// if(longMS < 0)
			// return Math.floor(longMS/1000/60/60/24);
			// else
			// return parseInt(longMS/1000/60/60/24);
		case 'w' :
			return parseInt(longMS / 1000 / 60 / 60 / 24 / 7);
		case 'h' :
			return parseInt(longMS / 1000 / 60 / 60);
		case 'n' :
			return parseInt(longMS / 1000 / 60);
		case 's' :
			return parseInt(longMS / 1000);
		case 'l' :
			return parseInt(longMS);
	}
}

// +---------------------------------------------------
// |reg生日
// |tod当前日期
// |cd提前提醒的天数范围
// +---------------------------------------------------
function getBirthday(reg, tod, cd)
{
	var d = new Date(reg),
		n = new Date(tod),
		y = n.getFullYear(),
		yd = new Date(
			y,
			n.getMonth(),
			n.getDate()
		),
		ds = (new Date(
			y,
			d.getMonth(),
			d.getDate()
		) - yd) / (1000 * 60 * 60 * 24),
		// 月日份相差天数
		ys = n.getFullYear() - d.getFullYear(); // 相差年数
	if (ds < -200)
	{// 修正类似1月1号提前5天的提醒，
		ds = (new Date(
			d.getFullYear() + (++ys),
			d.getMonth(),
			d.getDate()
		) - yd) / (1000 * 60 * 60 * 24);
	}
	if (ds > cd)
	{
		return null; // 不在范围内返回null，不提醒
	}
	// return [ys,ds] //返回相隔的年，日
	return ds; // 返回相隔的日
}

// +---------------------------------------------------
// | 求两个时间的天数差 日期格式为 YYYY-MM-dd
// +---------------------------------------------------
function daysBetween(DateOne, DateTwo)
{
	var OneMonth = DateOne.substring(
		5, DateOne.lastIndexOf('-')
	),
		OneDay = DateOne.substring(
			DateOne.length, DateOne.lastIndexOf('-') + 1
		),
		OneYear = DateOne.substring(
			0, DateOne.indexOf('-')
		),
		TwoMonth = DateTwo.substring(
			5, DateTwo.lastIndexOf('-')
		),
		TwoDay = DateTwo.substring(
			DateTwo.length, DateTwo.lastIndexOf('-') + 1
		),
		TwoYear = DateTwo.substring(
			0, DateTwo.indexOf('-')
		),
		cha = ((Date.parse(OneMonth + '/' + OneDay + '/' + OneYear) - Date.parse(TwoMonth + '/' + TwoDay + '/'
			+ TwoYear)) / 86400000);
	return Math.abs(cha);
}

// +---------------------------------------------------
// | 日期计算
// +---------------------------------------------------
Date.prototype.DateAdd = function(strInterval, Number)
{
	var dtTmp = this;
	switch (strInterval)
	{
		case 's' :
			return new Date(Date.parse(dtTmp) + (1000 * Number));
		case 'n' :
			return new Date(Date.parse(dtTmp) + (60000 * Number));
		case 'h' :
			return new Date(Date.parse(dtTmp) + (3600000 * Number));
		case 'd' :
			return new Date(Date.parse(dtTmp) + (86400000 * Number));
		case 'w' :
			return new Date(Date.parse(dtTmp) + ((86400000 * 7) * Number));
		case 'q' :
			return new Date(
				dtTmp.getFullYear(),
				(dtTmp.getMonth()) + Number * 3,
				dtTmp.getDate(),
				dtTmp.getHours(),
				dtTmp.getMinutes(),
				dtTmp.getSeconds()
			);
		case 'm' :
			return new Date(
				dtTmp.getFullYear(),
				(dtTmp.getMonth()) + Number,
				dtTmp.getDate(),
				dtTmp.getHours(),
				dtTmp.getMinutes(),
				dtTmp.getSeconds()
			);
		case 'y' :
			return new Date(
				(dtTmp.getFullYear() + Number),
				dtTmp.getMonth(),
				dtTmp.getDate(),
				dtTmp.getHours(),
				dtTmp.getMinutes(),
				dtTmp.getSeconds()
			);
	}
};

// +---------------------------------------------------
// | 日期格式化成指定的字符串格式
// +---------------------------------------------------
Date.prototype.format = function(format)
{
	var o = {
		'M+'	: this.getMonth() + 1, // month
		'd+'	: this.getDate(), // day
		'h+'	: this.getHours(), // hour
		'm+'	: this.getMinutes(), // minute
		's+'	: this.getSeconds(), // second
		'q+'	: Math.floor((this.getMonth() + 3) / 3), // quarter
		'S'		: this.getMilliseconds()
		// millisecond
	};
	if (/(y+)/.test(format))
		format = format.replace(
			RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length)
		);
	for (var k in o)
		if (new RegExp('(' + k + ')').test(format))
			format = format.replace(
				RegExp.$1, RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
			);
	return format;
};

// +---------------------------------------------------
// | 数组添加删除元素的方法
// +---------------------------------------------------
Array.prototype.del = function(n)
{
	// n表示第几项，从0开始算起。
	// prototype为对象原型，注意这里为对象增加自定义方法的方法。
	if (n < 0)
	{
		return this;
	}
	return this.slice(
		0, n
	).concat(this.slice(
		n + 1, this.length
	));
};

/*
 * 判断含有中文字符的字符串长度
 */
String.prototype.length2 = function()
{
	var cArr = this.match(/[^\x00-\xff]/ig);
	return this.length + (cArr === null ? 0 : cArr.length);
};

// 返回指定小数点位数：
// v数据
// e小数点后位数
function GetRound(v, e)
{
	if (isNaN(v))
	{
		return 0;
	}
	if (isNaN(e))
	{
		return v;
	}
	var t = Math.pow(
		10, e
	);
	return Math.round(v * t) / t;
}

// -------------------------------------------------------------------------------------------------
// 伪代理
// -------------------------------------------------------------------------------------------------
// 注：url是带参数的url
function client_http_proxy_callback(url, callback)
{
	try
	{
		var obj = client_core_interface();
		var reqid = obj.c(
			'C_SYS_GETHTML', url, callback
		);
		return reqid;
	}
	catch (e)
	{
		_trace('出错(http_proxy):' + e.message);
	}
}

function http_proxy_load(url, callback)
{
	var cachedata = null;
	if (__ajax_cache)
	{
		cachedata = ajax_url_cache_get(url);
	}
	if (cachedata)
	{
		return cachedata;
	}
	// 调用client_http_proxy_callback方法
}

function padLeft(str, lenght)
{
	if (str.length >= lenght)
	{
		return str;
	}
	return padLeft(
		"0" + str, lenght
	);
}

function isArray(val)
{
	return Object.prototype.toString.apply(val) === '[object Array]';
}

// +---------------------------------------------------
// | 调试
// +---------------------------------------------------
function _trace(s)
{
	try
	{
		var obj = client_core_interface();
		obj.r(
			'S_Debug_Print', s
		);
	}
	catch (e)
	{
	}
}

/*
 * 注册智能键盘
 */
function MSG_SYS_REGSMARTKB(cinfo)
{
	var tmpdata = "kbtype=contactlist,color=(150,0,150),pre=(,),sort=4,match_value=2,keywidth=15,cmd=(S_VIEW_GOTO WEBCOMM url=(.\\Web\\JJR\\index.htm?page=grxw&id=[M:KEY]))\r\n";
	tmpdata += cinfo;

	var obj = client_core_interface();
	obj.r(
		'S_SYS_REGSMARTKB', tmpdata
	);
}
