"use strict";

var jQuery = require("jquery");

/**
 * @ignore
 * 画布
 */
function MouseEvent(session, viewID, displayElem) {
	jQuery(displayElem).attr("tabindex", 0);//绑定div去响应键盘消息,需要自己设置焦点
	displayElem.style.outline = "none";
	
	var button = -1;//记录鼠标按下的键值

	// 当网络请求断开后,解绑鼠标监听
	session.addNetworkCloseListener(function(){
		jQuery(displayElem).off('mousedown mouseup mousemove mousewheel DOMMouseScroll mouseleave mouseenter dblclick', sendMouseEvent);
		jQuery(displayElem).off('touchend touchstart touchmove', sendTouchEvent);
	});
	
    // 处理鼠标事件
    function sendMouseEvent(e) {
		var obj = {
            type : -1,
            x: e.offsetX,
            y: e.offsetY
        };
		if(e.preventDefault) e.preventDefault();
        switch (e.type) {
			case 'mousedown':
				obj.type = 1;
				obj.button = e.which;
				button = obj.button;
				displayElem.focus(); //鼠标选中的元素切回焦点(因input元素的焦点在选择之后是不会切回的)
                break;
            case 'mouseup':
				obj.type = 2;
				obj.button = e.which;
				button = -1;
                break;
            case 'mousemove':
                obj.type = 3;
                break;
            case 'mousewheel':
                obj.wheelDelta = e.originalEvent.wheelDelta;
                obj.type = 4;
				displayElem.focus();
                break;
            case 'DOMMouseScroll':
                obj.wheelDelta = -e.originalEvent.detail * 40; // detail为3的倍数,wheelDelta是120的倍数
                obj.type = 4;
                break;
			case 'dblclick':
				obj.type = 5;
				break;	
			case 'mouseenter':
				jQuery(document).off("mouseup mousemove contextmenu", docMouseEvent);
				break;
			case 'mouseleave': 
				if (button >= 0){
					jQuery(document).on('mouseup mousemove contextmenu', docMouseEvent);
				}
				return false;	
            default:
                break;
        }
		
        if (obj.type > 0  && obj.x && obj.y) {
			session.request(viewID, "mouseEvent", obj);
			
			if(obj.type === 5){ //因浏览器dblclick不发送up消息,所以在此自己发送一次,不然后台的处理
				obj.type = 2;
				obj.button = 1;
				session.request(viewID, "mouseEvent", obj);
			}
        }
		
		//不能返回false,会同时调用preventDefault和stopPropagation
		return true;
    }
	
	function getElementTop(element){
		var actualTop = element.offsetTop;
        var current = element.offsetParent;
        while (current !== null){        
            actualTop += current.offsetTop;
            current = current.offsetParent;
        }
        return actualTop;
    }
	
	function getElementLeft(element){
        var actualLeft = element.offsetLeft;
        var current = element.offsetParent;
        while (current !== null){        
            actualLeft += current.offsetLeft;
            current = current.offsetParent;
        }
        return actualLeft;
    }
	
	function docMouseEvent(e) {
		var obj = {
			type: -1,
			x: e.pageX - getElementLeft(displayElem),
			y: e.pageY - getElementTop(displayElem)
		};
		switch (e.type) {
			case 'mousemove':
				e.preventDefault();
				obj.type = 3;
				break;
            case 'mouseup':
				obj.type = 2;
				obj.button = button;
				button = -1;
				break;
			case 'contextmenu':
				jQuery(document).off("mouseup mousemove contextmenu",docMouseEvent);//解绑会立刻生效,所以此时需要返回false
				return false;
			default:
                break;
		}
		
		if (obj.type > 0 && obj.x && obj.y) {
			session.request(viewID, "mouseEvent", obj);
        }
		return true;
	}
	
	var offsetLeft = 0;
	var offsetTop = 0;
	var touchRecord = [];
	var touchMoved = false;
	var touchNum = 0;
	var pointTouchstart = false;
	var touchmove = false;
	var pointTouchend = false;
	var startobj = {
			type : -1,
			x: -1,
            y: -1
		};
	
	function handleTouchStart(touchEven)
	{
		var obj = {
			type : -1,
			x: -1,
            y: -1
		};
		var trs = [];
		var touches = touchEven.originalEvent.changedTouches;
		for (var i = 0; i < touches.length; ++i)
		{
			trs.push({
				id: touches[i].identifier,
				x: touches[i].pageX - offsetLeft,
				y: touches[i].pageY - offsetTop
			});
		}
		for (var i = 0; i < trs.length; ++i)
		{
			touchRecord.push(trs[i]);
		}
		touchNum = touchRecord.length;
		if (touchNum === 1 && !touchMoved)
		{
			pointTouchstart = true;
			startobj.type = 1;
			startobj.button = 1;
			startobj.x = trs[0].x;
			startobj.y = trs[0].y;
		}
		
		return obj;
	}
	function handleTouchMove(touchEven)
	{
		var obj = {
			type : -1,
			x: -1,
            y: -1
		};
		if (touchNum > 2)
		{
			return obj;
		}
		var touches = touchEven.originalEvent.changedTouches;
		if (touches.length < 1)
		{
			return obj;
		}
		
		var trs = [];
		for (var i = 0; i < touches.length; ++i)
		{
			trs.push({
				id: touches[i].identifier,
				x: touches[i].pageX - offsetLeft,
				y: touches[i].pageY - offsetTop
			});
		}
		var preNum = touchNum;
		var newTouch = [];
		var oldTouch = [];
		for (var i = 0; i < trs.length; ++i)
		{
			var find = false;
			for (var j = 0; j < touchRecord.length; ++j)
			{
				if (trs[i].id === touchRecord[j].id)
				{
					find = true;
					oldTouch.push({
						id: trs[i].id,
						oldx: touchRecord[j].x,
						oldy: touchRecord[j].y,
						x: trs[i].x,
						y: trs[i].y,
						movex: trs[i].x - touchRecord[j].x,
						movey: trs[i].y - touchRecord[j].y
					});
					touchRecord[j] = trs[i];
				}
			}
			if (!find && !touchMoved)
			{
				newTouch.push(trs[i]);
				touchRecord.push(trs[i]);
			}
		}
		touchNum = touchRecord.length;
		if (touchNum > 2)
		{
			return obj;
		}
			
		if (trs.length === 1 && touchNum === 1)//rotate
		{
			obj.type = 3;
			if (!touchMoved)
			{
				obj.type = 1;
			}
			obj.button = 1;
			obj.x = trs[0].x;
			obj.y = trs[0].y;
			touchRecord[0] = trs[0];
		}
		else if (touchNum === 2)
		{
			var centerX = (touchRecord[0].x + touchRecord[1].x) / 2;
			var centerY = (touchRecord[0].y + touchRecord[1].y) / 2;
			if (!touchMoved)
			{
				obj.type = 1;
				obj.button = 2;
				obj.x = centerX;
				obj.y = centerY;
			}
			else if (oldTouch.length === 2)
			{
				var oldDistance = Math.sqrt((oldTouch[1].oldx - oldTouch[0].oldx)*(oldTouch[1].oldx - oldTouch[0].oldx) + (oldTouch[1].oldy - oldTouch[0].oldy)*(oldTouch[1].oldy - oldTouch[0].oldy));
				var newDistance = Math.sqrt((oldTouch[1].x - oldTouch[0].x)*(oldTouch[1].x - oldTouch[0].x) + (oldTouch[1].y - oldTouch[0].y)*(oldTouch[1].y - oldTouch[0].y));

				if (Math.abs(oldDistance - newDistance) < 10)//pan
				{
					obj.type = 3;
					obj.button = 2;
					obj.x = centerX;
					obj.y = centerY;
				}
				else
				{
					obj.wheelDelta = -120 * Math.ceil((oldDistance - newDistance)/Math.abs(oldDistance - newDistance)); //wheelDelta是120的倍数
					obj.type = 4;
					obj.x = centerX;
					obj.y = centerY;
				}
			}
		}
		
		touchMoved = true;
		
		return obj;
	}
	function handleTouchEnd(touchEven)
	{
		touchMoved = false;
		var obj = {
			type : -1,
			x: -1,
            y: -1
		};
		var trs = [];
		var touches = touchEven.originalEvent.changedTouches;
		for (var i = 0; i < touches.length; ++i)
		{
			trs.push({
				id: touches[i].identifier,
				x: touches[i].pageX - offsetLeft,
				y: touches[i].pageY - offsetTop
			});
		}
		if (touchNum === 1)
		{
			pointTouchend = true;
			obj.type = 2;
			obj.button = 1;
			obj.x = trs[0].x;
			obj.y = trs[0].y;
		}
		else if (touchNum === 2)
		{
			obj.type = 2;
			obj.button = 2;
			obj.x = trs[0].x;
			obj.y = trs[0].y;
		}
		touchRecord = [];
		return obj;
	}
	
	var touchend = false;
	function sendTouchEvent(e)
	{
		var obj = {
            type : -1,
            x: -1,
            y: -1
        };
		offsetLeft = getElementLeft(displayElem);
		offsetTop = getElementTop(displayElem);
		
		switch (e.type) {
            case 'touchstart':
                obj = handleTouchStart(e);
				displayElem.focus(); //鼠标选中的元素切回焦点(因input元素的焦点在选择之后是不会切回的)
                break;
            case 'touchend':
				touchend = true;
				obj = handleTouchEnd(e);
                break;
            case 'touchmove':
				touchmove = true;
				obj = handleTouchMove(e);
                break;
            default:
                break;
        }
		
		if(pointTouchstart && !touchmove && pointTouchend){
			session.request(viewID, "mouseEvent", startobj);
		}
		if(touchend){
			pointTouchend = false;
			touchmove = false;
			pointTouchstart = false;
			touchend = false;
		}
		
		if (obj.type > 0 && obj.x && obj.y) {
			session.request(viewID, "mouseEvent", obj);
        }
		e.preventDefault();
		
		//不能返回false,会同时调用preventDefault和stopPropagation
		return true;
	}
	
	jQuery(displayElem).on('mousedown', sendMouseEvent);
    jQuery(displayElem).on('mouseup', sendMouseEvent);
    jQuery(displayElem).on('mousemove', sendMouseEvent);
    jQuery(displayElem).on('mousewheel', sendMouseEvent);
    jQuery(displayElem).on('DOMMouseScroll', sendMouseEvent);
	jQuery(displayElem).on('mouseleave', sendMouseEvent);
	jQuery(displayElem).on('mouseenter', sendMouseEvent);
	jQuery(displayElem).on('dblclick', sendMouseEvent);
    jQuery(displayElem).on('contextmenu', false);
	jQuery(displayElem).on('touchstart', sendTouchEvent);
    jQuery(displayElem).on('touchmove', sendTouchEvent);
    jQuery(displayElem).on('touchend', sendTouchEvent);
	
    // 处理键盘事件
    function sendKeyboardEvent(e) {
        var code = e.keyCode ? e.keyCode : e.which;
		var obj = {
            code: code
        };

        switch (e.type) {
            case 'keydown':
                obj.type = 0;
                break;
            case 'keyup':
                obj.type = 1;
                break;
            default:
                break;
        }

        session.request(viewID, "keyEvent", obj);
     
        return true;
    }
    jQuery(displayElem).on('keydown', sendKeyboardEvent);
    jQuery(displayElem).on('keyup', sendKeyboardEvent);
};

module.exports = MouseEvent;