/*
 * =============================================================
 *
 * 猎宝前端简单库
 * 说明：为了phoneValidator库先写了一些简单的基础方法等。以后再封装。
 * 依赖：jquery.js、json2.min.js
 * ============================================================
 */
;
(function() {
	'use strict';

	/* 顶层命名空间和注册命名空间方法
	 * ---------------------------------------------------- */
	//LBUI顶层命名空间
	window.LBUI = window.LBUI || {};

	//命名空间注册
	window.regNS = function() {
		var a = arguments,
			o = null,
			i, j, d;
		for (i = 0; i < a.length; i = i + 1) {
			d = a[i].split(".");
			if (d[0] == "LBUI") {
				//如果是以LBUI开头的,则直接挂到window.LBUI下面;
				o = LBUI;
				j = 1;
			} else {
				//否则,直接挂到window下
				o = window;
				j = 0;
			}

			for (j; j < d.length; j = j + 1) {
				o[d[j]] = o[d[j]] || {};
				o = o[d[j]];
			}
		}

		return o;
	};


	/* 系统全局常量定义
	 * ---------------------------------------------------- */
	window.LBUI.constans = {
		//随机字符串
		CODE_STRING: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
		// TODO：
		AJAX_BASE_URL: '/api/',
		// 图形验证码检查结果
		CAPTCHA_VALIDATE_RESULT: {
			'E0': '正常',
			'E1000': '未输入有效的图形验证码参数',
			'E1001': '图形验证码不正确或已过期，请重新输入',
			'E1009': '请输入图片中的4位字符',
			'E1010': '验证失败：未知错误'
		},
		// 发送手机验证码结果
		SEND_PHONE_CODE_RESULT: {
			// 下面这些E开头的一般对应Errno
			'E0': '正常',
			'E1000': '发送失败：请输入有效的手机号码',
			'E1001': '发送失败：您未登录或您的登陆账号未绑定手机号码',
			'E1002': '发送失败：手机验证码发送太频繁(距离上次发送未超过60秒)',
			'E1003': '发送失败：您提供的手机号码今日已达到发送上线,24小时后才可以重发',
			'E1004': '发送失败：您输入的验证码不正确或已经过期，请重新输入',
			'E1005': '发送失败：该手机号码已经被注册',
			'E1010': '发送失败：未知错误',
			// 前台显示的相关细心
			'M0001': '手机校验码已经成功通过短信方式发送到您的手机，在5分钟内输入有效。',
			'M0002': '您的手机将接收到<em>010</em>区号开头的固定电话的呼叫，接通后将自动播报您的验证码，请注意接听。',
			'M0003': '<p>您最多只能尝试发送<em>X</em>次<em>Y</em>验证码。如仍未收到请刷新页面并更换号码后再试，或联系客服。</p>',
			'M0004':'<p>总是收不到短信？你也可以直接试试 <a href="###" class="pv-btn-voice">语音验证码&gt;&gt;</a></p>'
		}
	};

	/* 扩展String对象的原生功能
	 * ---------------------------------------------------- */
	//判断当前字符串是否以str开始 先判断是否存在function是避免和js原生方法冲突，自定义方法的效率不如原生的高
	if (typeof String.prototype.startsWith != 'function') {
		String.prototype.startsWith = function(str) {
			return this.slice(0, str.length) == str;
		};
	}　　　
	//判断当前字符串是否以str结束
	if (typeof String.prototype.endsWith != 'function') {
		String.prototype.endsWith = function(str) {
			return this.slice(-str.length) == str;
		};
	}

	/* 扩充jQuery功能
	 * ---------------------------------------------------- */
	$.extend({
		isEmpty: function(obj, allowBlank) {

			return obj === null || obj === undefined || (!allowBlank ? obj === '' : false);
		},
		// 下面这几个是常用方法。。。。。。
		isString: function(obj) {
			return toString.call(obj) == '[object ' + name + ']';
		},
		isNumber: function(obj) {
			return toString.call(obj) == '[object ' + name + ']';
		},
		isDate: function(obj) {
			return toString.call(obj) == '[object ' + name + ']';
		}
	});

	/* 工具方法
	 * ---------------------------------------------------- */
	window.LBUI.utils = {
		//生成随机的uuid字符串的简易算法
		UUID: function() {
			return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
				var r = Math.random() * 16 | 0,
					v = c == 'x' ? r : (r & 0x3 | 0x8);
				return v.toString(16);
			});
		},

		//生成指定长度的随机字符串。默认为8位字符长度
		randomString: function(size) {
			// size:需要生成的随机字符串长度.默认为8个字符长度
			size = size || 8;
			var max_num = LBUI.constans.CODE_STRING.length + 1;
			var new_pass = '';
			while (size > 0) {
				new_pass += LBUI.constans.CODE_STRING.charAt(Math.floor(Math.random() * max_num));
				size--;
			}
			return new_pass;
		},

		//获得1970-1-1至今的秒数
		timestamp: function() {
			return Math.round(new Date().getTime() / 1000.0);
		},

		// 时间戳（1970-1-1起的秒数）转换成日期对象
		ts2Date: function(timestamp) {
			// timestamp : 1970-1-1 起的秒数
			if (!$.isNumber(timestamp)) timestamp = 0;
			return new Date(timestamp * 1000);
		},

		// 时间戳（1970-1-1起的秒数）格式化输出
		ts2DateString: function(timestamp, format) {
			// format:格式字符串，完整的如（默认值）：yyyy-MM-dd hh:mm:ss
			// 这里
			if (!$.isString(format)) format = "yyyy-MM-dd hh:mm:ss";
			return this.ts2Date(timestamp).format(format);
		},

		// 将JSON字符串转换成JSON对象
		// 注意:该方法比较安全,不会跑出语法异常
		toJSON: function(text) {
			try {
				return JSON.parse(text);
			} catch (err) {
				return null;
			}
		},

		// 返回错误消息的标准结构
		rstError: function(errno, msg, data) {
			return {
				"errno": errno, //错误消息
				"msg": msg || '', //异常的详细信息，如果有
				"data": data || '' //错误相关的数据
			};
		},
		// 检查Email格式
		checkEmail: function(email) {
			// 检查Email格式是否正确
			// email:需要检查的Email地址
			if (!email) return false;

			if (!/^[\.\w]([(\/)(\-)(\+).\w])*@([(\-)\w]{1,64}\.){1,7}[(\-)\w]{1,64}$/
				.test(email)) {
				return false;
			} else {
				if (email && email != "" && (email.indexOf("@") != -1)) {
					var indexOfA = email.indexOf("@");
					var name = email.substring(0, indexOfA);
					if (name.length > 64 || email.length > 256) {
						return false;
					} else {
						return true;
					}
				}
			}
			return false;
		},
		// 检查手机号码
		checkPhoneNumber: function(phone) {
			phone = phone || '';
			return /^1[34578][0-9]{9}$/.test(phone);
		},

		// 检查图形验证码格式是否正确
		checkCaptcha: function(code) {
			code = code || '';
			return /^[a-z0-9]{4}$/i.test(code);
		},
		// 检查手机验证码
		checkPhoneCode: function(code) {
			return /^[0-9]{6}$/.test(code || '');
		},
		// 构建自定义的HTTP头信息
		buildHttpHeader: function() {
			//TODO:以后可以扩充，比如添加授权验证等信息
			return {};
		}

	};

	/* AJAX相关
	 * ---------------------------------------------------- */

	//Ajax服务基类

	function AjaxService(url) {
		//请求的默认地址.
		//可以在实例中重写.
		//实际的请求地址是url+action
		this.url = '';

	};

	//Ajax类的原型。
	AjaxService.prototype = {
		defaults: {
			buildUrl: function(url, action, args) {
				//TODO:判断URL结尾以及Action有效性
				url = url || '';
				action = action || '';
				// 最后生成的请求的url是url+action的形式
				return url + action;
			},
			//TODO：是否启用接口授权验证功能。这个以后可以扩充。
			auth: false,
			//超时时间：1分钟
			timeoutPeriod: 60 * 1000,
			//默认请求类型
			method: 'POST',
			//默认返回的数据格式
			dataType: 'json',
			global: true
		},

		//发起GET
		G: function(action, args, option) {

			var o = option || {};
			o.method = 'GET';

			return this.R(action, args, o);
		},

		//发起Ajax请求,默认是POST方法.
		R: function(action, args, option) {

			option = $.extend({}, this.defaults, option);

			var url = this.url || LBUI.constans.AJAX_BASE_URL;

			//构造URL
			if ($.isFunction(option.buildUrl)) {
				url = option.buildUrl(url, action, args);
			}

			//注意:这里直接返回经过deferred包装的ajax对象
			return $.ajax({
				//请求类型
				type: option.method,
				//请求地址
				url: url, //ajax对象在代码一加载的时候就已经实例化了。
				//超时时间
				timeout: option.timeoutPeriod,
				//是否触发全局事件
				global: option.global,
				//请求上下文
				context: {
					action: action,
					args: args,
					description: option.description
				},
				//请求参数
				data: args,
				//TODO：以后可扩展。
				headers: LBUI.utils.buildHttpHeader()
			});
		}
	};

	//Ajax类。
	LBUI.Ajax = AjaxService;



	/* 对服务器端AJAX接口请求调用的封装。暂时放在这个地方。
	 * ======================================================= */

	// 注册命名空间
	//window.regNS('LBUI.service');
	LBUI.service=LBUI.service||{};

	var Validator = function() {};

	$.extend(Validator.prototype, $.extend(new LBUI.Ajax, {
		//请求地址,实际是的url+action
		//除非请求地址和LBUI.Ajax基类内的url地址不一样时,才需要设置该属性.
		// 默认使用的base url在LBUI.constans.AJAX_BASE_URL常量中定义
		//url: '',

		// DEMO方法
		ping: function() {

			var option = {
				auth: false, //接口是否需要身份验证.默认为true;对于不需要身份验证的接口,需要设置该值为false.
				description: "检测服务器状态"
			};
			//this.G()是get请求;this.R()是post请求;
			//G和R方法的参数都是一样的;
			//G(action,para,option)
			// action:请求的方法,会和url拼接成一个完整的请求地址,
			//		比如ping方法,最后实际请求的地址是http://www.7881.com/api/ping
			// para:该action接受的参数,JSON对象
			// option:选项JSON对象,目前用于调试模式.对于不需要身份验证的接口,需要明确设置option.auth=false;
			return this.G('ping', null, option);
		},
		// 请求发送手机验证码
		sendPhoneCode: function(type, phone, act, captcha, data_str) {
			// @param type String： 手机验证码类型：0-短信；1-语音；
			// @param phone String：手机号码。可能为空；
			// @param act String：要求发送手机验证码的行为动作代码；预留
			// @param captcha String：图形验证码；额外参数可选。
			// @param data_str String:
			var option = {
				auth: false,
				description: "发送手机验证码"
			};
			// 使用GET请求发送
			return this.R('send_phone_code.action', {
				t: type,
				act: act,
				phone: phone,
				captcha: captcha,
				data_str: data_str
			}, option);
		},
		// 验证图形验证码的正确性
		validateCaptcha: function(code, act) {
			// @param code String：需要验证的图形验证码；
			// @param act String：图形验证码对应的行为动作；
			var option = {
				auth: false,
				description: "验证图形验证码"
			};

			if (!code) {
				// TODO：以后可以在AJAX基类中暴露参数验证结果的方法；
				// 这样，在发起请求之前就可以对一些参见有效性进行校验，
				// 并且，当发现参数无效的时候，直接返回结果对象（Deferred），而无需请求；
			}
			// 使用GET请求发送
			return this.G('validate_captcha.action', {
				code: code,
				act: act,
				timestamp: new Date().getTime()
			}, option);
		},
		// 验证手机验证码是否正确
		validatePhoneCode: function(code, type, phone, userID, act) {
			// @param type String： 手机验证码类型：0-短信；1-语音；
			// @param phone String：手机号码。可能为空；
			// @param act String：要求发送手机验证码的行为动作代码；预留
			// @param code String：需要校验的手机验证码；
			// @param userID String：用户编号，一般用于注册过程。
			var option = {
				auth: false,
				description: "发送手机验证码"
			};
			// 使用GET请求发送
			return this.R('validate_phone_code.action', {
				t: type,
				act: act,
				phone: phone,
				code: code,
				userID: userID
			}, option);
		}
	}));

	LBUI.service.Validator = new Validator();



	/* 提供对图形验证码、手机验证码的服务器端校验
	 * 可独立使用。
	 * ======================================================= */
	// 图形验证码和手机短信校验的方法封装
	//window.regNS('LBUI.validator');

	LBUI.validator = {
		// 校验图形验证码
		checkCaptcha: function(callback, captcha, action) {
			// @param captcha string : 需要校验的图形验证码；
			// @param action string ： 该图形验证码对应的动作行为代码
			// @param callback Function/Object：校验完成后的回调函数，签名如下：
			// callback(success,msg):其中success表示校验成功与否的；msg表示校验失败的提示文字；

			// 先检查图形验证码格式是否正确
			if (LBUI.utils.checkCaptcha(captcha)) {
				// 如果输入的格式有效，则到服务器端校验
				LBUI.service.Validator.validateCaptcha(
					captcha,
					action
					// self._options.captchaActionCode
				).done(function(rst) {
					// 调用成功
					if (rst && rst.errno == 0) {
						// 如果图形验证验证成功了
						// 则开始调用发送短信的回调
						if ($.isFunction(callback)) {
							callback(true);
						};
					} else {

						callback(false, LBUI.constans.CAPTCHA_VALIDATE_RESULT['E' + rst.errno] || LBUI.constans.CAPTCHA_VALIDATE_RESULT['E1010']);
					}

				}).fail(function(error) {
					// 记录下
					// 调用失败
					callback(false, LBUI.constans.CAPTCHA_VALIDATE_RESULT['E1010']);

				});
			} else {
				callback(false, LBUI.constans.CAPTCHA_VALIDATE_RESULT['E1009']);
				// 不调用callback
			}
		},


		// 校验手机验证码
		checkPhoneCode: function(callback, code, phone, userID, type, action) {
			// @param callback Function ： 接收校验结果的回调；签名如下：
			// callback(success,msg):其中success表示校验成功与否的；msg表示校验失败的提示文字；
			// @param code string ：需要校验的手机验证码；
			// @param phone string ： 手机号码。如果未指定，则会从当前登录用户的信息中取得；
			// @param userID string ： 用户编号。如果制定了phone参数，则必须指定userID参数；
			// @param type string ：验证码类型，0-短信；1-语音。默认为0；
			// @param action string ： 行为代码

			if (LBUI.utils.checkPhoneCode(code)) {
				// validatePhoneCode: function(code, type, phone, userID, act) {
				// 如果输入的格式有效，则到服务器端校验
				LBUI.service.Validator.validatePhoneCode(
					code,
					type,
					phone,
					userID,
					action
				).done(function(rst) {
					// 调用成功
					if (rst && rst.errno == 0) {
						// 如果验证成功了
						if ($.isFunction(callback)) {
							callback(true);
						};
					} else {

						callback(false, LBUI.constans.SEND_PHONE_CODE_RESULT['E' + rst.errno] || LBUI.constans.SEND_PHONE_CODE_RESULT['E1010']);
					}

				}).fail(function(error) {
					// 记录下
					// 调用失败
					callback(false, LBUI.constans.SEND_PHONE_CODE_RESULT['E1010']);

				});
			} else {
				callback(false, LBUI.constans.SEND_PHONE_CODE_RESULT['E1009']);
				// 不调用callback
			}
		}
	};
})();