/**
 * 滑块验证
 * @author good_idea
 * @date 2019年1月11日 上午10:48:41
 */
layui.define(["jquery", "layer", "form"], function (exports) {
	"use strict";
	var $ = layui.jquery,
		form = layui.form,
		layer = layui.layer,
		device = layui.device(),
		sliderVerify = {
			read: (function () {
				var css =
					".slider-item{height:38px;line-height:38px;background-color:#d0d0d0;position:relative;border: 1px solid white;}.slider-bg{position:absolute;width:40px;height:100%;z-index:100}.slider-btn{width:40px;height:96%;position:absolute;border:1px solid #ccc;cursor:move;text-align:center;background-color:#fff;user-select:none;color:#666;z-index:120}.slider-btn-success{font-size:26px}.slider-text{position:absolute;text-align:center;width:100%;height:100%;user-select:none;font-size:14px;color:#fff;z-index:120}.slider-error{animation:glow 800ms ease-out infinite alternate;}@keyframes glow{0%{border-color:#e6e6e6}100%{border-color:#ff5722}}",
					style = document.createElement("style");
				style.innerHTML = css;
				style.type = "text/css";
				($("head link:last")[0] && $("head link:last").after(style)) ||
					$("head").append(style);
			})()
		},
		dom = function (d) {
			return d[0];
		},
		thisSliderVerify = function () {
			var that = this;
			return {
				isOk: function () {
					return that.isOk.call(that);
				},
				reset: function () {
					return that.reset.call(that);
				},
				version: '1.7'
			};
		},
		MOD_NAME = "sdvy",
		MOD_BTN = "slider-btn",
		MOD_BG = "slider-bg",
		MOD_TEXT = "slider-text",
		MOD_NEXT = "layui-icon-next",
		MOD_OK = "layui-icon-ok-circle",
		MOD_BTN_SUCCESS = "slider-btn-success",
		MOD_DEFAULT_BG = "layui-bg-green",
		MOD_ERROR_BORDER = "slider-error",
		MOD_CONFIG_TEXT = "请拖动滑块验证",
		MOD_CONFIG_SUCCESS = "ok",
		Class = function (option) {
			var that = this;
			that.config = $.extend({}, that.config, option);
			that.render();
		};

	//默认配置
	Class.prototype.config = {
		elem: "",
		onOk: null,
		isOk: false,
		isAutoVerify: true,
		bg: MOD_DEFAULT_BG, //默认滑块颜色
		text: MOD_CONFIG_TEXT
	};

	Class.prototype.render = function () {
		var that = this,
			option = that.config,
			elem = $(option.elem);
		if (!elem[0]) return;
		if (option.domid) option.domid.remove();
		option.domid = that.createIdNum();
		var sliderDom = $(
			[
				'<div id="' +
				option.domid +
				'"' +
				(option.isAutoVerify ? 'lay-verify="sliderVerify"' : "") +
				'class="slider-item">',
				'<div class="' + MOD_BG + " " + option.bg + '"></div>',
				'<div class="' + MOD_TEXT + '">' + option.text + "</div>",
				'<div class="' + MOD_BTN + ' layui-icon layui-icon-next"></div>'
			].join("")
		);
		elem.hide().after(sliderDom);
		option.domid = $("#" + option.domid);

		that.events();
		//自动验证
		if (option.isAutoVerify) {
			form.verify({
				sliderVerify: function (value, dom) {
					if (!value) {
						dom.classList.add(MOD_ERROR_BORDER);
						return option.text;
					}
				}
			});
		}
	};
	Class.prototype.isMobile = function () {
		return (
			device.os == "ios" ||
			device.os == "android" ||
			device.android ||
			device.ios
		) || (device.weixin && typeof device.weixin === Boolean);
	};
	Class.prototype.createIdNum = function () {
		return (
			MOD_NAME +
			(+new Date()).toString() +
			Math.random()
				.toString()
				.substr(2, 7)
		);
	};
	//验证是否验证成功
	Class.prototype.isOk = function () {
		return this.config.isOk;
	};

	Class.prototype.error = function (msg) {
		return layer.msg(msg, {
			icon: 5
		});
	};

	Class.prototype.distance = function () {
		var container = this.config.container;
		return container.box.offsetWidth - container.btn.offsetWidth; //滑动成功的宽度（距离）
	};

	//重置组件
	Class.prototype.reset = function () {
		this.config.isOk = false;
		return this.render();
	};

	//重置
	Class.prototype.resize = function (distance) {
		var that = this,
			container = that.config.container;
		var distance = distance || that.distance();
		container.btn.style.left = distance + "px";
		container.bg.style.width = distance + "px";
	};

	//取消动画
	Class.prototype.cancelTransition = function () {
		var container = this.config.container;
		this.config.domid[0].classList.remove(MOD_ERROR_BORDER);
		container.btn.style.transition = "";
		container.bg.style.transition = "";
	};
	//按下
	Class.prototype.down = function (e) {
		var that = this,
			option = that.config,
			container = option.container,
			e = e || window.event,
			//按下的坐标
			downX = e.clientX || e.touches[0].clientX;
		//每次将过渡去掉
		that.cancelTransition();
		var move = function (e) {
			that.move(downX, e);
		};
		that.events.move = move;
		//mobile移动
		if (that.isMobile()) {

			document.addEventListener("touchmove", that.events.move);
		} else {
			//pc移动
			document.onmousemove = move;
		}
		//处理部分浏览器滑动时左右翻页
		if(navigator.userAgent.indexOf("UCBrowser") > -1){
			e.preventDefault()
		}
	};
	//移动
	Class.prototype.move = function (down, e) {
		var that = this,
			option = that.config,
			container = option.container;
		var e = e || window.event;
		//鼠标移动后的水平位置
		var moveX = e.clientX || e.touches[0].clientX;
		//鼠标水平位置的偏移量（鼠标移动时的位置 - 鼠标按下时的位置）
		var offsetX = moveX - down;

		//判断一下：鼠标水平移动的距离 与 滑动成功的距离 之间的关系
		if (offsetX > container.distance) {
			offsetX = container.distance; //如果滑过了终点，就将它停留在终点位置
		} else if (offsetX < 0) {
			offsetX = 0; //滑到了起点的左侧，将它重置为起点位置
		}
		container.btn.style.left = offsetX + "px";
		container.bg.style.width = offsetX + "px";

		//鼠标的水平移动距离 = 滑动成功的宽度
		if (offsetX == container.distance) {
			//1.滑动成功后的样式
			container.text.innerHTML = MOD_CONFIG_SUCCESS;
			var com = window.getComputedStyle
				? window.getComputedStyle(container.bg, null)
				: container.bg.currentStyle;
			container.btn.style.border = "1px solid " + com.backgroundColor;
			container.btn.style.color = com.backgroundColor;
			container.btn.classList.remove(MOD_NEXT);
			container.btn.classList.add(MOD_OK, MOD_BTN_SUCCESS);
			option.isOk = true;
			container.box.value = true;
			//成功后，清除掉鼠标按下事件和移动事件（因为移动时并不会涉及到鼠标松开事件）
			//干掉mobile事件
			if (that.isMobile()) {
				container.btn.removeEventListener(
					"touchstart",
					that.events.down,
					false
				);
				document.removeEventListener(
					"touchmove",
					that.events.move,
					false
				);
			} else {
				container.btn.onmousedown = null;
				document.onmousemove = null;
			}
			//最后调用回调
			option.onOk && typeof option.onOk == "function" && option.onOk();
			return;
		}
		var seup = function (e) {
			that.stop(e);
		};
		that.events.seup = seup;
		if (that.isMobile()) {
			document.addEventListener("touchend", seup);
		} else {
			document.onmouseup = seup;
		}
	};
	//放开
	Class.prototype.stop = function (e) {
		var that = this,
			option = that.config,
			container = option.container;
		//鼠标松开，如果滑到了终点，则验证通过
		if (that.isOk()) {
			return;
		} else {
			container.btn.style.left = 0;
			container.bg.style.width = 0;
			container.btn.style.transition = "left 1s";
			container.bg.style.transition = "width 1s";
		}
		//鼠标松开了，不需要拖动就清除鼠标移动和松开事件。
		document.onmousemove = null;
		document.onmouseup = null;
		if (that.isMobile()) {
			document.removeEventListener("touchmove", that.events.move, false);
			document.removeEventListener("touchend", that.events.seup, false);
		}
	};
	//事件
	Class.prototype.events = function () {
		var that = this,
			option = that.config;
		if (!option.domid) return that.error("创建滑块验证失败");

		var btn = option.domid.find("." + MOD_BTN),
			bg = option.domid.find("." + MOD_BG),
			text = option.domid.find("." + MOD_TEXT),
			container = {
				box: dom(option.domid),
				btn: dom(btn),
				bg: dom(bg),
				text: dom(text)
			};
		option.container = container;
		container.distance = that.distance();
		var down = function (e) {
			that.down(e);
		};
		that.events.down = down;
		if (that.isMobile()) {
			container.btn.addEventListener("touchstart", that.events.down);
		} else {
			container.btn.onmousedown = down;
		}
		var $dom = $(window);
		$dom.on("resize", option.domid, function () {
			if (that.config.isOk) {
				//重新计算页面被拉伸
				that.resize();
			}else{
				that.render();
			}
		});
	};

	sliderVerify.render = function (option) {
		var inst = new Class(option);
		return thisSliderVerify.call(inst);
	};

	exports(MOD_NAME, sliderVerify);
});