--------------------------------------------------------------------------------
-- SimNetwork
-- input.lua
-- Handles user input:	- rotation of 3D scene
--			- zoom in/out
--------------------------------------------------------------------------------
SimNetwork_INPUT = true

if not SimNetwork_SCENE then	dofile("scene.lua") end

-- Global variables
-- ----------------

input = {
	MouseX = 0,		-- Absolute location of mouse pointer in coordinates
	MouseY = 0,		-- of Electro's window (and 2D scene)
	
	MouseLDown = false,	-- Status of mouse buttons (false for up, true for down)
	MouseRDown = false,
	MouseMDown = false,

	scrollLeft = false,	-- Indicates whether left, right, up, or down
	scrollRight = false,	-- keys are pressed (for scrolling the map)
	scrollUp = false,
	scrollDown = false,
	
	rotateLeft = false,
	rotateRight = false,
	zoomIn = false,
	zoomOut = false,
	toggleWidget = false,	-- Indicates whether key to toggle widget is
				-- pressed or not
}	

zoomRate = 2

selection = {
	current = nil
}

--mouse cursor
mouse = {			
	imgNormal = "data/cursorNormal.png",
	imgCable = "data/cursorCable.png",
	imgRouter = "data/cursorRouter.png",
	imgDemolish = "data/cursorDemolish.png",
	normal = nil,
	cable = nil,
	router = nil,
	demolish = nil,
	cameraMouse = nil
}	


-- -----------------------------------------------------------------------------
-- Function: initializeCursors()
-- Inputs:	none
-- Returns:	none
-- Description: create all sprites necessary for mourse cursors, initializes the mouse cursors
-- -----------------------------------------------------------------------------
function initializeCursors()
	cameraMouse = E.create_camera(E.camera_type_orthogonal)
	E.set_entity_position(cameraMouse,0,-viewport.T*2,0)
	
	pivot = E.create_pivot()
	
	mouse.normal = create_overlay(mouse.imgNormal)
	mouse.cable = create_overlay(mouse.imgCable)
	mouse.router = create_overlay(mouse.imgRouter)
	mouse.demolish = create_overlay(mouse.imgDemolish)
	
	E.parent_entity(pivot,cameraMouse)
	E.parent_entity(mouse.normal,pivot)
	E.parent_entity(mouse.cable,pivot)
	E.parent_entity(mouse.router,pivot)
	E.parent_entity(mouse.demolish,pivot)
	
	E.set_entity_position(pivot,input.MouseX,-input.MouseY,0)
	
end

-- -----------------------------------------------------------------------------
-- Function: moveCursor()
-- Inputs:	cursor
-- Returns:	none
-- Description: moves cursor to where the mouse x and y position is on the screen
-- -----------------------------------------------------------------------------
function moveCursor(cursor)
	E.set_entity_position(cursor,input.MouseX,-input.MouseY,0)
end

-- -----------------------------------------------------------------------------
-- Function: showCursor()
-- Inputs:	cursor
-- Returns:	none
-- Description: shows the cursor on the screen
-- -----------------------------------------------------------------------------
function showCursor(cursor)
	E.set_entity_flags(cursor,E.entity_flag_hidden,false)
end

-- -----------------------------------------------------------------------------
-- Function: hideCursor()
-- Inputs:	cursor
-- Returns:	none
-- Description: hides the cursor on the screen
-- -----------------------------------------------------------------------------
function hideCursor(cursor)
	E.set_entity_flags(cursor,E.entity_flag_hidden,true)
end

-- -----------------------------------------------------------------------------
-- Function: hideCursors()
-- Inputs:	none
-- Returns:	none
-- Description: hides all cursors on the screen
-- -----------------------------------------------------------------------------
function hideCursors()
	E.set_entity_flags(mouse.normal,E.entity_flag_hidden,true)
	E.set_entity_flags(mouse.cable,E.entity_flag_hidden,true)
	E.set_entity_flags(mouse.router,E.entity_flag_hidden,true)
	E.set_entity_flags(mouse.demolish,E.entity_flag_hidden,true)
end

-- -----------------------------------------------------------------------------
-- Function: handle_3d_rotation
-- Inputs:	dx, dy (integer): relative pointer movement
-- Returns:	boolean: indicates whether screen needs refresh
-- Description: rotates 3D scene about X and Y, also restricts rotation
-- to (-360, 360) about Y, [0, 90] about X
-- -----------------------------------------------------------------------------
function handle_3d_rotation(dx, dy)
	local refresh = false
	local xRotation = 0
	local yRotation = 0
	
	if dx ~= 0 then
		-- Rotate 3D scene about Y axis 
		yRotation = dx
		refresh = true
	end
	
	if dy ~= 0 then
		-- Rotate 3D scene about X axis
		xRotation = dy
		refresh = true
	end
	
	if refresh then
		-- gameScene:registerRotation(0, yRotation)
		gameScene:rotate(xRotation, yRotation)	
	end
	
	return refresh
end

-- -----------------------------------------------------------------------------
-- Function: handle_3d_zoom
-- Inputs:	dy (integer): relative pointer movement
-- Returns:	boolean: indicates whether screen needs refresh
-- Description: Zooms in/out
-- -----------------------------------------------------------------------------
function handle_3d_zoom(dy)
	if dy ~= 0 then
		local zoom = (dy / 500) * zoomRate
		gameScene:changeZoom(zoom)
		return true
	end
	return false
end

function handle_scroll()
	
	-- transV:	camera translation vector
	--		[1]: Horizontal scroll (negative for L, positive for R)
	--		[2]: Vertical scroll (negativce for D, positive for Up)
	--		[3]: Zoom In/Out (positive for Out, negative for In)
	--		[4]: Rotation (about Y)
	local transV = {0, 0, 0, 0}
	
	if input.scrollLeft then
		transV[1] = -1
	elseif input.scrollRight then
		transV[1] = 1
	end
	
	if input.scrollDown then
		transV[2] = 1
	elseif input.scrollUp then
		transV[2] = -1
	end
	
	if input.zoomOut then
		transV[3] = 1
	elseif input.zoomIn then
		transV[3] = -1
	end
	
	if input.rotateLeft then
		transV[4] = 1
	elseif input.rotateRight then
		transV[4] = -1
	end
	
	if transV[1] ~= 0 or transV[2] ~= 0 or transV[3] ~= 0 or transV[4] ~= 0 then
		gameScene:moveCamera(transV)
	end
end

-- -----------------------------------------------------------------------------
-- Function: do_click() (callback)
-- Inputs:	b: button clicked
--		s: status; true for pressed, false for released
-- Description: handle toolbar clicking (selecting tools) and 3D mouse picking
-- in 3D scene.
-- -----------------------------------------------------------------------------
function do_click(b, s)

	if b==1 then
		input.MouseLDown = s
		
		if	input.MouseLDown and input.MouseX > 0 and 
			input.MouseX < toolbarWidth and 
			input.MouseY > 0 and input.MouseY < 32 and s then
			-- left click within tool bar
			return handle_toolbar_click()
		
		elseif s then
			-- report left click to Scene
			gameScene:mouseClick("left")
		end
	
	elseif b==3 then
		input.MouseRDown = s
		if s then
			-- report right click to Scene
			gameScene:mouseClick("right")
		end

	elseif b==4 then
		-- Mouse wheel down
		gameScene:moveCamera({0, 0, -1, 0})
		return true
	elseif b==5 then
		-- Mouse wheel up
		gameScene:moveCamera({0, 0, 1, 0})
		return true
	elseif b == 2 then
		input.MouseMDown = s
	end
	
	return false
	
end

-- -----------------------------------------------------------------------------
-- Function: do_point() (callback)
-- Inputs:	dx, dy: pointer movement, relative to last position
-- Description: Check whether Right/Middle button are down and perform
-- 3D rotation/zoom repspectively
-- -----------------------------------------------------------------------------
function do_point(dx, dy)

	input.MouseX = input.MouseX + dx
	input.MouseY = input.MouseY + dy
		
	local refresh = false

	if not input.MouseLDown and not input.MouseRDown then
	
		if	input.MouseX > 0 and 
			input.MouseX < toolbarWidth and 
			input.MouseY > 0 and input.MouseY < 32 then
		
			-- Mouse within toolbar range
			refresh = handle_toolbar_hover()		
		else
			-- Mouse within 3D Scene
			refresh = handle_toolbar_leave()
			gameScene:mouseTrack()
		end
	end
	
	return refresh
end

-- -----------------------------------------------------------------------------
-- Function: do_keyboard() (callback)
-- Inputs:	b: button, s: pressed/released
-- -----------------------------------------------------------------------------
function do_keyboard(b, s)
	
	-- Scrolling
	if b == E.key_left and s then
		input.scrollLeft = true
	elseif b == E.key_left and not s then
		input.scrollLeft = false
	elseif b == E.key_down and s then
		input.scrollDown = true
	elseif b == E.key_down and not s then
		input.scrollDown = false
	elseif b == E.key_right and s then
		input.scrollRight = true
	elseif b == E.key_right and not s then
		input.scrollRight = false
	elseif b == E.key_up and s then
		input.scrollUp = true
	elseif b == E.key_up and not s then
		input.scrollUp = false
	
	-- Rotation about Y
	elseif b == E.key_a and s then		-- A
		input.rotateLeft = true
	elseif b == E.key_a and not s then
		input.rotateLeft = false
	elseif b == E.key_s and s then		-- S
		input.rotateRight = true
	elseif b == E.key_s and not s then
		input.rotateRight = false
	
	-- Zoom In/Out	
	elseif b == E.key_w and s then		-- W
		input.zoomIn = true
	elseif b == E.key_w and not s then
		input.zoomIn = false
	
	elseif b == E.key_z and s then		-- Z
		input.zoomOut = true
	elseif b == E.key_z and not s then
		input.zoomOut = false
	
	-- toggle widget of selected entity
	elseif b == E.key_space and s then
		input.toggleWidget = true
	end
end

function do_timer(dt)
	handle_scroll()
	
	hideCursors()
	moveCursor(mouse.normal)
	moveCursor(mouse.router)
	moveCursor(mouse.cable)
	moveCursor(mouse.demolish)
	
	if selectedTool == nil then
		showCursor(mouse.normal)
	elseif selectedTool == "demolish" then
		showCursor(mouse.demolish)
	elseif selectedTool == "cable1" then
		showCursor(mouse.cable)
	elseif selectedTool == "cable10" then
		showCursor(mouse.cable)
	elseif selectedTool == "cable100" then
		showCursor(mouse.cable)
	elseif selectedTool == "router2" then
		showCursor(mouse.router)
	elseif selectedTool == "router4" then
		showCursor(mouse.router)
	elseif selectedTool == "router8" then
		showCursor(mouse.router)
	end
	
	if input.toggleWidget then
		input.toggleWidget = false
		gameScene:toggleWidget()
	end
	return true
end
