//___________________________________
//                                   \
// Digitharia: Input Engine. version 1.0
//___________________________________/


/*

*/
//----------------------------------------------------------------------------//

InputEngine.prototype.RepressMouseDefault = 200; // 200ms = 5 times a second repress
InputEngine.prototype.PRESSEDMOUSE = {}; //holds objects: {start:time, clicks:n ticks:n, next:time}
InputEngine.prototype.MOUSEACTION = {  }; // ONMOUSEDOWN ONMOUSEUP ONMOUSEPRESS ONMOUSECLICK clickdelay DELAY
InputEngine.prototype.mouseX = 0;
InputEngine.prototype.mouseY = 0;
InputEngine.prototype.current = undefined;

//  allowed button values are: MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE
InputEngine.prototype.addClick = function(button, x1,y1, x2,y2, mousepress, mouseunpress, click, clickdelay, repress, repressdelay, onhover, hoverout, that, name){
	var o = {};
	if(mousepress) o.ONMOUSEDOWN = typeof mousepress=='function' ? mousepress : Function(mousepress);
	if(mouseunpress) o.ONMOUSEUP = typeof mouseunpress=='function' ? mouseunpress : Function(mouseunpress);
	if(repress) o.ONMOUSEPRESS = typeof repress=='function' ? repress : Function(repress);
	if(click) o.ONMOUSECLICK = typeof click=='function' ? click : Function(click);
	o.clickdelay = typeof clickdelay != 'undefined' ? clickdelay : this.RepressMouseDefault;
	o.DELAY = typeof repressdelay != 'undefined' ? repressdelay : this.RepressMouseDefault;
	if(onhover) o.ONMOUSEHOVERIN = typeof onhover=='function' ? onhover : Function(onhover);
	if(hoverout) o.ONMOUSEHOVEROUT = typeof hoverout=='function' ? hoverout : Function(hoverout);
	o.x1 = x1;
	o.y1 = y1;
	o.x2 = x2;
	o.y2 = y2;
	o.name = name || x1+"_"+y1+"_"+x2+"_"+y2;
	o.that = that;
	o.hover = false;
	o.mousedown = false;
	o.button = button;
	if(typeof button != 'number') Abort("addClick() error: unknown button. Allowed button values are: MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE")
	if(!this.MOUSEACTION[button])
		this.MOUSEACTION[button] = {};
	this.MOUSEACTION[button][o.name] = o;
	LL.write("added button"+button+" "+o.name);
};

InputEngine.prototype.BindClick = InputEngine.prototype.addClick;

InputEngine.prototype.delClick =function(button, key){
	if(this.MOUSEACTION[button])
		delete this.MOUSEACTION[button][key];
};

InputEngine.prototype.UnbindClick = InputEngine.prototype.delClick;

InputEngine.prototype.handleMouseInput = function() {
	this.mousemoved = false;
	if(this.mouseX != GetMouseX()){
		this.mouseX = GetMouseX();
		this.mousemoved = true;
	}
	if(this.mouseY != GetMouseY()){
		this.mouseY = GetMouseY();
		this.mousemoved = true;
	}
	if(this.mousemoved){
		LL.write("mousemoved ("+this.mouseX+","+this.mouseY+")" );
		//Handle drags, mousein/mouseout/mouseover
		this.last = this.current;
		this.current = undefined;
		for(var mousekey=0 ; mousekey<2; ++mousekey){
			if(this.MOUSEACTION[mousekey])
				for(var o in this.MOUSEACTION[mousekey]){
					if( this.checkMouseHover(this.MOUSEACTION[mousekey][o], this.mouseX, this.mouseY) )
						continue;
				}
		}
	}

	for(var BUTTON in this.MOUSEACTION){
		if(IsMouseButtonPressed(parseInt(BUTTON)) && this.current && this.current.button == BUTTON)
				this._click(BUTTON, this.current);
	}

	for(var BUTTON in this.PRESSEDMOUSE){
		if(IsMouseButtonPressed(parseInt(BUTTON))) continue;
		if(this.current && this.current.button == BUTTON)
			this._unclick(BUTTON, this.current);
		delete this.PRESSEDMOUSE[BUTTON];
	}
}

// InputEngine.prototype.PRESSEDMOUSE = {}; //holds objects: {start:time, clicks:n ticks:n, next:time}
// InputEngine.prototype.MOUSEACTION = {}; // ONMOUSEDOWN ONMOUSEUP ONMOUSEPRESS ONMOUSECLICK clickdelay DELAY

InputEngine.prototype.checkMouseHover = function(o,x,y){
//LL.write("("+o.x1+","+o.y1+","+o.x2+","+o.y2+") in ("+x+","+y+")" );
	if(x<o.x1||o.x2<x||y<o.y1||o.y2<y){
		if(o.pressed){
			o.pressed = false;
			if(o.ONMOUSEUP)
				o.ONMOUSEUP();
		}
		if(o.hover){
			o.hover = false;
			o.ONMOUSEHOVEROUT();
		}
		return;
	}
	if(!o.hover){
		LL.write("hover over "+o.name);
		o.hover = true;
		o.ONMOUSEHOVERIN();
	}
	this.current = o;
	return true; 
}


/**
 * Internal function: Register a keyboard BUTTON as being clicked and act accordingly
 */
InputEngine.prototype._click = function(BUTTON, mousekey){
	var now = GetTime();
	mousekey.pressed = true;
	if(this.PRESSEDMOUSE[BUTTON]){
		if(this.PRESSEDMOUSE[BUTTON].next<now){
			LL.write("reclicking "+BUTTON+" "+now);
			++this.PRESSEDMOUSE[BUTTON].tick;
			this.PRESSEDMOUSE[BUTTON].next = now + mousekey.DELAY;
			if(mousekey.ONMOUSEPRESS)
				mousekey.ONMOUSEPRESS(this.PRESSEDMOUSE[BUTTON].tick, this.mouseX, this.mouseY);
			LL.write("reclicked  "+BUTTON+" "+this.PRESSEDMOUSE[BUTTON].next +";"+mousekey.DELAY);
		};
		if(this.PRESSEDMOUSE[BUTTON].stop){
			++this.PRESSEDMOUSE[BUTTON].click;
			LL.write("++click="+this.PRESSEDMOUSE[BUTTON].click);
			this.PRESSEDMOUSE[BUTTON].stop=false;
			this.PRESSEDMOUSE[BUTTON].nextclick = now + this.MOUSEACTION[BUTTON].clickdelay;
		};
		//LL.write("SKIP "+BUTTON+":"+this.PRESSEDMOUSE[BUTTON].next+"!<"+now)
	}else{
		LL.write("Mousedown "+BUTTON);
		this.PRESSEDMOUSE[BUTTON] = { start: now, tick: 0, next: (now+mousekey.DELAY), click:1, nextclick: (now+mousekey.clickdelay) };
		if(mousekey.ONMOUSEDOWN)
			mousekey.ONMOUSEDOWN(this.PRESSEDMOUSE[BUTTON].click, this.mouseX, this.mouseY);
	}
}

/**
 * Internal function: Register a keyboard BUTTON as being unclicked and act accordingly
 */
InputEngine.prototype._unclick = function(BUTTON, mousekey){
	mousekey.pressed = false;
	if(this.PRESSEDMOUSE[BUTTON].stop){
		if(this.PRESSEDMOUSE[BUTTON].stop < GetTime()){
	LL.write("real unclick")
			if(mousekey.ONMOUSECLICK)
				mousekey.ONMOUSECLICK(this.PRESSEDMOUSE[BUTTON].click,this.mouseX, this.mouseY);
			delete this.PRESSEDMOUSE[BUTTON];
		}
	}else{
	LL.write("pre unclick")
		this.PRESSEDMOUSE[BUTTON].stop = GetTime() + this.MOUSEACTION[BUTTON].clickdelay;
		if(mousekey.ONMOUSEUP)
			mousekey.ONMOUSEUP(this.PRESSEDMOUSE[BUTTON].tick,this.mouseX, this.mouseY);
	}
}

/**
 * Trigger the key action functions directly
 */
InputEngine.prototype.ONMOUSEDOWN = function(BUTTON){ if(this.MOUSEACTION[BUTTON].ONMOUSEDOWN) this.MOUSEACTION[BUTTON].ONMOUSEDOWN.apply(this, [0]); }
InputEngine.prototype.ONMOUSEUP = function(BUTTON, tick){ if(this.MOUSEACTION[BUTTON].ONMOUSEUP) this.MOUSEACTION[BUTTON].ONMOUSEUP.apply(this, [tick]); }
InputEngine.prototype.ONMOUSEPRESS = function(BUTTON, tick){ if(this.MOUSEACTION[BUTTON].ONMOUSEPRESS) this.MOUSEACTION[BUTTON].ONMOUSEPRESS.apply(this, [tick]); }

//----------------------------------------------------------------------------//

/**
 * Mocking functions, emulate keyclickes through MockMousePress() instead of getting them from the keyboard.
 */
InputEngine.prototype.MockMouse = {_:0};
InputEngine.prototype.MockMousePress= function(BUTTON, ms) {
	if(!this.MockMouse[BUTTON])
		this.MockMouse['_']++ ;
	var now=GetTime();
	this.MockMouse[BUTTON] = {start:now, tick:0, mocknext:now+ms, next: (now + this.MOUSEACTION[BUTTON]?this.MOUSEACTION[BUTTON].DELAY:this.ReclickDefault)}
};

InputEngine.prototype.MockMouseUnclickAll= function() {
	for(var BUTTON in this.MockMouse){ this.MockMouse[BUTTON].mocknext = 0; };
}

InputEngine.prototype.MockMouseClear= function() { this.MockMouse = {_:0}; };

InputEngine.prototype.MockMouseboardInput = function() {
	if(this.MockMouse['_']){
		var BUTTON,now;
		for(var BUTTON in this.MockMouse){
			if(BUTTON == '_') continue;
			now = GetTime();
			if(this.MockMouse[BUTTON].mocknext<now){
				delete this.MockMouse[BUTTON];
				--this.MockMouse['_'];
			}
			if(!this.MOUSEACTION[BUTTON]) continue;
			this._click(BUTTON);
		}
	}
	for(var BUTTON in this.PRESSEDMOUSE){
		if(this.MockMouse[BUTTON]) continue;
		this._unclick(BUTTON);
	}
}
//--------------------------------------
InputEngine.prototype.CreateMouseImage = function(ccolor, cursor) {
	if(!ccolor) ccolor = {
		0:CreateColor(0,0,0,0),                 //Transparant
		1:CreateColor(0, 0, 0, 255),            //Black
		2:CreateColor(156, 156, 156, 255),      //Gray-dark
		3:CreateColor(192, 192, 192, 255),      //Gray-light
		4:CreateColor(255, 255, 255, 255),      //White
		9:CreateColor(0, 0, 0, 64),             //shadow
	};
	if(!cursor) cursor =  [
		[1,1,1,0,0,0,0,0,0,0],
		[1,2,2,1,1,0,0,0,0,0],
		[1,3,4,2,2,1,1,0,0,0],
		[0,1,3,4,3,2,2,1,1,0],
		[0,1,3,4,3,3,2,2,2,1],
		[0,0,1,3,4,3,3,2,1,9],
		[0,0,1,3,4,4,3,1,9,0],
		[0,0,0,1,3,4,4,3,1,9],
		[0,0,0,1,2,1,4,3,2,1],
		[0,0,0,0,1,9,1,2,1,9],
		[0,0,0,0,0,0,0,1,9,0]
	];
	var s = CreateSurface(cursor[0].length, cursor.length, CreateColor(0,0,0,0));
	s.setBlendMode(REPLACE);
	for(var j=0;j<cursor.length;++j){
		for(var i=0;i<cursor[j].length;++i){
			s.setPixel(i,j,ccolor[cursor[j][i]]);
		}
	}
	return s.createImage();
}

InputEngine.prototype.InitMouse = function(ccolor, cursor){
	this.mouseImage = this.CreateMouseImage(ccolor, cursor);
}

InputEngine.prototype.DisplayMouse = function(){
	this.mouseImage.blit(GetMouseX(),GetMouseY());	
}
