local Util = require 'core/appkit/lua/util'
local SimpleProject= require 'core/appkit/lua/simple_project'
Project.PlayerHud = Project.PlayerHud or {}
local PlayerHud = Project.PlayerHud
local move = {forward = false, backward = false, left = false, right = false}
local stamina = 100
local score = 0
local sprint_multiplier = 1

PlayerHud.paused = false
PlayerHud.exit = false

local Vector3 = stingray.Vector3
local Vector3Box = stingray.Vector3Box
local Keyboard = stingray.Keyboard

local hud_level = nil

-- Audio functions
local function play_pause_on()
    if stingray.Wwise then
        stingray.Wwise.load_bank("content/audio/default")
        local wwise_world = stingray.Wwise.wwise_world(SimpleProject.world)
        stingray.WwiseWorld.trigger_event(wwise_world, "sfx_UI_pause_on")
    end
end

local function play_pause_off()
    if stingray.Wwise then
        stingray.Wwise.load_bank("content/audio/default")
        local wwise_world = stingray.Wwise.wwise_world(SimpleProject.world)
        stingray.WwiseWorld.trigger_event(wwise_world, "sfx_UI_pause_off")
    end
end

local function play_accept()
    if stingray.Wwise then
        stingray.Wwise.load_bank("content/audio/default")
        local wwise_world = stingray.Wwise.wwise_world(SimpleProject.world)
        stingray.WwiseWorld.trigger_event(wwise_world, "sfx_UI_accept")
    end
end


-- Scaleform is an engine plugin and is required for this file.
if scaleform == nil then 
	PlayerHud = { init_hud = function() end,
				  update   = function() end,
				  shutdown = function() end,
				  exit_level = function() end,
				  get_motion_input = function() end,
				  check_toggle_camera = function() end,
				  check_sprint = function() end,
				  check_jump = function() end
				}
	return PlayerHud
end

function PlayerHud:on_custom_event(evt)

	if evt.name == "analog_stick" then
		if evt.data.action == "jump" then
			self.input.jump = true
		end
		if evt.data.action == "walk" then
			local move = Vector3(evt.data.x, -evt.data.y,0)
			self.input.move:store(Vector3.normalize(move))
		end
		if evt.data.action == "look"  then
			local pan = Vector3(evt.data.x, evt.data.y, 0)
			self.input.pan:store(4 * Vector3.normalize(pan)) --speed up pan rate a bit for look.
		end
	end

	if evt.name == "button_click" then
		if evt.data.action == "start_sprint" then
			self.input.sprint = true
			local move = Vector3(0, 1, 0)
			self.input.move:store(Vector3.normalize(move))
		end

		if evt.data.action == "stop_sprint" then
			local move = Vector3(0, 0, 0)
			self.input.move:store(Vector3.normalize(move))
			self.input.sprint = false
		end

		if evt.data.action == "toggle_camera" then
			self.input.toggle_camera = true
		end
		if evt.data.action == "return" then
			self.input.exit_level = true
		end
	end

	if  Util.is_pc() then 
		if evt.name == "pause" then
			PlayerHud.paused = true
			play_pause_on()
		elseif evt.name == "unpause" then
			PlayerHud.paused = false
			play_pause_off()
		elseif evt.name == "main_menu" then
			play_accept()
			PlayerHud.exit = true
		end
	end

	if  Util.use_touch() then
		if evt.data.action == "return" then
			PlayerHud.exit = true
		end
	end

	if stingray.Window then
		stingray.Window.set_show_cursor(PlayerHud.paused)
	end
end

function PlayerHud:init_hud()
	--Used for mobile hud controls but it simplifies the logic in player if they're always available.
	self.input = {
		pan = Vector3Box(Vector3(0, 0, 0)),
		move = Vector3Box(Vector3(0, 0, 0)),
		jump = false,
		toggle_camera = false,
		sprint = false,
		exit_level = false
	}

	PlayerHud.paused = false
	PlayerHud.exit = false

	--On PC show only the dpad hud.
	if  Util.is_pc() then 
		local current_level = SimpleProject.level
		scaleform.Stingray.load_project_and_scene("content/ui/advanced_hud.s2d/advanced_hud");
		hud_level = current_level
	end

	--On Touch devices display touch specific hud
	if  Util.use_touch() then
		local current_level = SimpleProject.level
		scaleform.Stingray.load_project_and_scene("content/ui/basic_mobile_hud.s2d/basic_mobile_hud");
		hud_level = current_level
	end

	--Register a custom listener to check for different controls.
	local custom_listener = PlayerHud.custom_listener
	custom_listener = scaleform.EventListener.create(custom_listener, function (e) PlayerHud.on_custom_event(PlayerHud,e) end)
	PlayerHud.custom_listener = custom_listener
	scaleform.EventListener.connect(custom_listener, scaleform.EventTypes.Custom)
end

function PlayerHud:shutdown(level)
	if scaleform then
		scaleform.Stingray.unload_project();
		PlayerHud.custom_listener = nil
		hud_level = nil
	end
end

local function update_pc_hud(dt)
	local event = {
		eventId = scaleform.EventTypes.Custom,
		name = nil,
		data = nil
	}
	--Controlling HUD features through custom messages and key presses.
	if stingray.Keyboard.pressed(stingray.Keyboard.button_index("w"))  then
		move.forward = true
	end
	
	if stingray.Keyboard.pressed(stingray.Keyboard.button_index("a")) then
		move.left = true
	end

	if stingray.Keyboard.pressed(stingray.Keyboard.button_index("s"))  then
		move.backward = true
	end
	
	if stingray.Keyboard.pressed(stingray.Keyboard.button_index("d")) then
		move.right = true
	end

	if stingray.Keyboard.pressed(stingray.Keyboard.button_index("left shift")) then
		sprint_multiplier = 2
	end

	if stingray.Keyboard.released(stingray.Keyboard.button_index("w"))  then
		move.forward = false
	end
	
	if stingray.Keyboard.released(stingray.Keyboard.button_index("a")) then
		move.left = false
	end

	if stingray.Keyboard.released(stingray.Keyboard.button_index("s"))  then
		move.backward = false
	end
	
	if stingray.Keyboard.released(stingray.Keyboard.button_index("d")) then
		move.right = false
	end

	if stingray.Keyboard.released(stingray.Keyboard.button_index("left shift")) then
		sprint_multiplier = 1
	end

	if not PlayerHud.paused and (move.forward or move.backward or move.left or move.right) then
		event.name = "stamina_changed"

		stamina = stamina - 2 * dt * sprint_multiplier
		if stamina < 0 then
			stamina = 100
		end

		event.data = {value = stamina}

		scaleform.Stage.dispatch_event(event)

		event.name = "score_changed"
		score = score + 10 * dt * sprint_multiplier

		event.data = {value = score}

		scaleform.Stage.dispatch_event(event)
	end
end

function PlayerHud:update(dt)
	if Util.is_pc() then
		update_pc_hud(dt)
	end
end

--Implement handlers for touch controls to override appkit input_mapper and project specific controls.
function PlayerHud:get_motion_input()
	local input = self.input
	return {move = input.move:unbox(), pan = input.pan:unbox()}
end

function PlayerHud:check_toggle_camera()
	local ret = self.input.toggle_camera
	self.input.toggle_camera = false
	return ret
end

function PlayerHud:check_sprint()
	return self.input.sprint
end

function PlayerHud:check_jump()
	local ret = self.input.jump
	self.input.jump = false
	return ret
end

function PlayerHud:exit_level()
	local ret = self.input.exit_level
	self.input.exit_level = false
	return ret
end

return PlayerHud