var manipulateTool = {
	name: "manipulate",
	description: "Manipulate the node",
	section: "foo",
	icon: "imgs/mini-icon-ball.png",
	keyShortcut: 87, //W

	circle_size: 50,

	state: null,
	state_action: false,
	circle_center: vec3.create(),
	gizmo_center: vec3.create(),
	click_pos: vec3.create(),

	getGizmoLocalCenter: function( node, result )
	{
		result = result || vec3.create();

		if( ToolsModule.center_system == "instances" && node._instances && node._instances.length )
		{
			for(var i in node._instances)
				vec3.add( result, result, node._instances[i].oobb ); //node._instances[i].center
			vec3.scale(result,result,1/node._instances.length);
		}

		return result;
	},

	//called form ToolsModule
	renderEditor: function(camera)
	{
		if(!EditorView.mustRenderGizmos()) 
			return;

		var selection = SelectionModule.getSelection();
		if(!selection) 
			return;
		var node = selection.node; //could be null

		var gizmo_model = ToolUtils.getSelectionMatrix();
		if(!gizmo_model)
			return null;

		//var pos = node.transform.getGlobalPosition( this.gizmo_center );
		var pos = selection.instance.constructor === LS.SceneNode ?  this.getGizmoLocalCenter(node) : vec3.create();

		mat4.multiplyVec3( pos, gizmo_model, pos );
		this.gizmo_center.set( pos );

		//ToolUtils.prepareDrawing();
		//var camera = ToolUtils.getCamera();
		var camera2D = ToolUtils.enableCamera2D( camera );
		var pos2D = camera.project(pos);

		if( pos2D[2] < 0 ) 
			return;
		pos2D[2] = 0;
		this.circle_center.set(pos2D);

		//now render the gizmo
		gl.disable(gl.DEPTH_TEST);
		gl.enable(gl.BLEND);
		gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
		LS.Draw.push();
		LS.Draw.translate(pos2D);

		var circle_size = this.circle_size;

		var color = (node && node._is_bone) ? [1,0.1,1] : [1,0.6,0.1];

		//center circle
		LS.Draw.scale(5,5,5);
		LS.Draw.setColor( color );
		LS.Draw.setAlpha(0.5);
		LS.Draw.renderMesh( EditorView.debug_render.circle_mesh, gl.TRIANGLES );

		//rotate line
		LS.Draw.scale(circle_size / 5.0, circle_size / 5.0, circle_size / 5.0);
		LS.Draw.setAlpha( this.state == "rotate" ? 0.6 : 0.3 );
		LS.Draw.renderMesh( EditorView.debug_render.circle_empty_mesh, gl.LINE_LOOP );

		//move circle
		LS.Draw.scale(0.95,0.95,0.95);
		LS.Draw.setAlpha( this.state == "move" ? 0.4 : 0.2 );
		LS.Draw.renderMesh( EditorView.debug_render.circle_mesh, gl.TRIANGLES );
		LS.Draw.pop();

		gl.enable(gl.DEPTH_TEST);
	},

	mousedown: function(e)
	{
		if(!this.enabled) 
			return;
		if(e.which != 1)  //LEFT (do not use GL.LEFT_MOUSE_BUTTON because which use special format)
			return;

		var selection = SelectionModule.getSelection();
		if(!selection) 
			return;
		var node = selection.node; //could be null

		var gizmo_model = ToolUtils.getSelectionMatrix();
		if(!gizmo_model)
			return null;
		var pos = selection.instance.constructor === LS.SceneNode ?  this.getGizmoLocalCenter(node) : vec3.create();
		mat4.multiplyVec3( pos, gizmo_model, pos );

		var camera = ToolUtils.getCamera(e);
		var camera2D = ToolUtils.getCamera2D(camera);
		var pos2D = camera.project(pos);

		if(pos2D[2] < 0) //behind camera
			return;
		pos2D[2] = 0;

		this.circle_center.set(pos2D);

		var state = this.checkCursorState(e);
		this.state = state;
		this.updateCursor();

		if(e.shiftKey)
		{
			if(!state)
			{
				return;
			}
			else
			{
				var instances = SelectionModule.cloneSelectedInstance();
				if(instances)
					SelectionModule.setMultipleSelection(instances, false);
			}
		}
		else if(state) //there is an action performed
		{
			if(node)
			{
				if(node._is_bone && node.parentNode && node.parentNode._is_bone && !e.ctrlKey)
					ToolUtils.saveNodeTransformUndo(node.parentNode);
				else 
					ToolUtils.saveSelectionTransformUndo();
			}
		}

		if(state == "move")
		{
			this.state_action = true;
			ToolUtils.testPerpendicularPlane( e.canvasx, gl.canvas.height - e.canvasy, this.gizmo_center, this.click_pos );
		}
		else if(state == "rotate")
		{
			this.state_action = true;
			ToolUtils.testPerpendicularPlane( e.canvasx, gl.canvas.height - e.canvasy, this.gizmo_center, this.click_pos );
		}
		else
			this.state_action = false;
	},

	mouseup: function(e)
	{
		if(this.state_action)
			EditorModule.refreshAttributes();

		var selection_info = SelectionModule.getSelection();
		if( selection_info && selection_info.node && selection_info.node === LS.GlobalScene.root )
			CORE.afterUserAction("component_changed", selection_info.instance );
		else
			ToolUtils.afterSelectionTransform();

		this.state_action = false;
	},

	mousemove: function(e)
	{
		var mouse = vec3.fromValues( e.canvasx, e.canvasy, 0 );
		var old = this.state;

		//do not change state if there is an action in course
		if(!this.state_action)
		{
			this.state = this.checkCursorState(e);
			this.updateCursor();
		}

		var ret = null;
		if(e.dragging && this.state_action && e.which == 1)
			ret = this.onMouseDrag(e);

		EditorModule.updateInspector();

		if(this.state != old)
			LS.GlobalScene.refresh();

		return ret;
	},

	mousewheel: function(e)
	{
		if(!e.dragging)
			return;


		var selection = SelectionModule.getSelection();
		if(!selection) 
			return;
		var node = selection.node; //could be null

		if(this.state == "move")
		{
			var camera = ToolUtils.getCamera(e);
			var eye = camera.getEye();
			var delta = vec3.sub(vec3.create(), eye, this.gizmo_center );
			vec3.scale(delta,delta, (e.wheel < 0 ? 0.02 : -0.02) );
			var T = mat4.setTranslation( mat4.create(), delta );
	
			if( node && node._is_bone && node.parentNode && node.parentNode._is_bone && !e.ctrlKey )
				ToolUtils.applyTransformMatrixToBone(T);
			else
				ToolUtils.applyTransformMatrixToSelection(T);

			ToolUtils.testPerpendicularPlane( e.canvasx, gl.canvas.height - e.canvasy, this.gizmo_center, this.click_pos );
			EditorModule.updateInspector();
			LS.GlobalScene.refresh();
			return true;		
		}
	},

	onMouseDrag: function(e)
	{
		var selection = SelectionModule.getSelection();
		if(!selection) 
			return;
		var node = selection.node; //could be null

		var gizmo_model = ToolUtils.getSelectionMatrix();
		if(!gizmo_model)
			return null;
		var pos = selection.instance.constructor === LS.SceneNode ?  this.getGizmoLocalCenter(node) : vec3.create();
		mat4.multiplyVec3( pos, gizmo_model, pos );

		if(this.state == "move")
		{
			var result = vec3.create();
			ToolUtils.testPerpendicularPlane( e.canvasx, gl.canvas.height - e.canvasy, this.click_pos, result );
			var delta = vec3.sub(vec3.create(), result, this.click_pos);
			this.click_pos.set( result );

			var T = mat4.create();
			mat4.translate(T,T,delta);

			if(node && node._is_bone && node.parentNode && node.parentNode._is_bone && !e.ctrlKey)
				ToolUtils.applyTransformMatrixToBone(T);
			else
				ToolUtils.applyTransformMatrixToSelection(T);

		}
		else if(this.state == "rotate")
		{
			var camera = ToolUtils.getCamera(e);
			var result = vec3.create();
			ToolUtils.testPerpendicularPlane( e.canvasx, gl.canvas.height - e.canvasy, this.gizmo_center, result );
			var A = vec3.sub( vec3.create(), this.click_pos, this.gizmo_center );
			var B = vec3.sub( vec3.create(), result, this.gizmo_center );
			this.click_pos.set( result );
			vec3.normalize(A,A);
			vec3.normalize(B,B);
			//var axis = vec3.sub( vec3.create(), this.gizmo_center, camera.getEye() );
			var axis = vec3.cross( result, A,B );
			var angle = -Math.acos( Math.clamp( vec3.dot(A,B), -1,1) );
			//var angle = vec2.computeSignedAngle(A,B);
			if(angle != 0)
			{
				//need to know direction
				//var direction = vec3.dot( axis, vec3.cross(vec3.create(), A,B));
				//if(direction > 0) angle *= -1;

				var R = mat4.create();
				vec3.normalize(axis,axis);
				mat4.rotate( R, R, angle, axis );

				ToolUtils.applyTransformMatrixToSelection( R, this.gizmo_center );
			}
		}

		return this.state != null;
	},

	checkCursorState: function(e)
	{
		var mouse = vec3.fromValues( e.canvasx, e.canvasy, 0 );
		var dist = vec3.distance( mouse, this.circle_center );
		if( dist < (this.circle_size * 0.95) )
			return "move";
		else if( dist < this.circle_size * 1.05 )
			return "rotate";
		return null;
	},

	updateCursor: function()
	{
		var selection = SelectionModule.getSelection();
		if(!selection)
		{
			gl.canvas.style.cursor = null;
			return;
		}

		if(this.state == "move")
			gl.canvas.style.cursor = "move";
		else if(this.state == "rotate")
			gl.canvas.style.cursor = "e-resize";
		else
			gl.canvas.style.cursor = null;
	}
};

ToolsModule.registerTool(manipulateTool);

