local fluid_aim_fire = 0
local fluid_aim_aim = 0
local fluid_aim_jammed = false
local fluid_aim_switch_weapon = false
local fluid_aim_toggle = false
local fluid_aim_reset_fire_on_load = true

-- TimeEvents
-- Need to re-evaluate Attempt to fire and Attempt to aim is necesary
-- Attempt to fire
local function fluid_aim_delay_fire_func()
	if fluid_aim_fire then
		level.press_action(bind_to_dik(key_bindings.kWPN_FIRE))
	end
	return true
end

-- Attempt to aim
local function fluid_aim_delay_aim_func()
	if fluid_aim_aim then
		level.press_action(bind_to_dik(key_bindings.kWPN_ZOOM))
	end
	return true
end

-- Delay before weapon can aim after switch
local function fluid_aim_delay_switch_weapon_func()
	fluid_aim_switch_weapon = true
	return true
end

-- Actor On Update(Every tick)
local function actor_on_update()
	if not (db.actor:alive()) then
		return
	end

	-- Check if fire or aim is pressed
	fluid_aim_fire = key_state(bind_to_dik(key_bindings.kWPN_FIRE)) ~= 0
	if ui_options.get("control/general/aim_toggle") then
		if not (fluid_aim_toggle) then
			fluid_aim_aim = key_state(bind_to_dik(key_bindings.kWPN_ZOOM)) ~= 0
		end
	else
		fluid_aim_aim = key_state(bind_to_dik(key_bindings.kWPN_ZOOM)) ~= 0
	end

	-- Check if it's a weapon or binocular
	local wpn = db.actor:active_item()
	local is_weapon = wpn and (IsWeapon(wpn) or SYS_GetParam(0,wpn:section(),"class") == "WP_BINOC") or false
	if (is_weapon) then
		local state = wpn:get_state()

		-- Melee
		if (SYS_GetParam(0,wpn:section(),"kind") == "w_melee") then
			-- Not in menus
			if (actor_menu.last_mode == 0) and (pda.dialog_closed == true) and (not Check_UI()) and (not db.actor:has_info("ui_pda")) then
				if fluid_aim_fire and not (state == 5) and not fluid_aim_reset_fire_on_load then
					level.press_action(bind_to_dik(key_bindings.kWPN_FIRE))
				elseif fluid_aim_aim and not (state == 6) then
					level.press_action(bind_to_dik(key_bindings.kWPN_ZOOM))
				end
			end
		-- Firearms 
		elseif not (SYS_GetParam(0,wpn:section(),"kind") == "w_melee") then
			-- First frame when weapon is being equip
			if state == 3 then
				fluid_aim_switch_weapon = false
				local wpn_kind = SYS_GetParam(0,wpn:section(),"kind")
				
				-- Implement ltx weapon name list for custom equip aim time
				
				-- Time require before you can aim when switching weapons
				-- Default Pistol
				if (wpn_kind == "w_pistol") then
					CreateTimeEvent("fluid_aim_delay_switch_weapon", "fluid_aim_delay_switch_weapon", 0.1, fluid_aim_delay_switch_weapon_func)
				
				-- Seems a bit over powered
				-- Default Smg
				--elseif (wpn_kind == "w_smg") then
					--CreateTimeEvent("fluid_aim_delay_switch_weapon", "fluid_aim_delay_switch_weapon", 0.6, fluid_aim_delay_switch_weapon_func)
				
				-- Default Shotgun
				--elseif (wpn_kind == "w_shotgun") then
					--CreateTimeEvent("fluid_aim_delay_switch_weapon", "fluid_aim_delay_switch_weapon", 0.8, fluid_aim_delay_switch_weapon_func)
				
				-- Default Rifle
				--elseif (wpn_kind == "w_rifle") then
					--CreateTimeEvent("fluid_aim_delay_switch_weapon", "fluid_aim_delay_switch_weapon", 0.9, fluid_aim_delay_switch_weapon_func)
				
				-- Default Sniper aim delay
				--elseif (wpn_kind == "w_sniper") then
					--CreateTimeEvent("fluid_aim_delay_switch_weapon", "fluid_aim_delay_switch_weapon", 1.2, fluid_aim_delay_switch_weapon_func)
				
				-- Unlisted
				--else
					--CreateTimeEvent("fluid_aim_delay_switch_weapon", "fluid_aim_delay_switch_weapon", 0.9, fluid_aim_delay_switch_weapon_func)
				end
			end
			
			-- Not in menus
			if (actor_menu.last_mode == 0) and (pda.dialog_closed == true) and (not Check_UI()) and (not db.actor:has_info("ui_pda")) then
				-- Override weapon to idle state after delay timer
				switch_weapon_state(wpn, fluid_aim_switch_weapon)
				
				-- Fire weapon logic
				if fluid_aim_fire and not IsMoveState("mcSprint") and not fluid_aim_reset_fire_on_load then
					if state == 5 then
						fluid_aim_jammed = false
					end

					-- Automatic weapon continue fire after ADS 
					if axr_main.weapon_is_zoomed and not (state == 5 or fluid_aim_jammed) and (wpn:get_ammo_in_magazine() > 0) and wpn:cast_Weapon():GetFireMode() == -1 then
						level.release_action(bind_to_dik(key_bindings.kWPN_FIRE))
						CreateTimeEvent("fluid_aim_delay_fire", "fluid_aim_delay_fire", 0, fluid_aim_delay_fire_func)
					end

					-- Queue fire
					if game.actor_weapon_lowered() or not (state == 0 or state == 2 or state == 3 or state == 5) then
						CreateTimeEvent("fluid_aim_delay_fire", "fluid_aim_delay_fire", 0, fluid_aim_delay_fire_func)
					end
				end
				
				-- Aim weapon logic
				if fluid_aim_aim then
					if not (axr_main.weapon_is_zoomed) and (game.actor_weapon_lowered() or not (state == 2 or state == 3 or state == 5)) then
						CreateTimeEvent("fluid_aim_delay_aim", "fluid_aim_delay_aim", 0, fluid_aim_delay_aim_func)
					end
				end
			end
		end
	end
	wpn = nil
end

-- Weapons states found in xrs debug tools
-- local states = {
-- 	eIdle,				--= 0
-- 	eShowing,			--= 1
-- 	eHiding,			--= 2
-- 	eHidden,			--= 3
-- 	eBore,				--= 4
-- 	eFire,				--= 5
-- 	eFire2, 			--= 6
-- 	eReload, 			--= 7
-- 	eMisfire, 			--= 8
-- 	eMagEmpty,			--= 9
-- 	eSwitch				--= 10
-- }

-- Functions
-- Prematurely force the weapon to aim or shoot after weapon switch delay
function switch_weapon_state (wpn, fluid_aim_switch_weapon)
	if wpn:get_state() == 1 and not (wpn:weapon_is_scope()) and not (SYS_GetParam(0,wpn:section(),"kind") == "w_sniper") then
		if fluid_aim_switch_weapon == true then
			wpn:switch_state(0)
			fluid_aim_switch_weapon = false
		end
	end
end

-- Weapon Jammed to prevent jam sound when aiming and shooting
local function actor_on_weapon_jammed()
	fluid_aim_jammed = true
end

-- Key press to prevent toggle aim release from aiming instantly again
local function on_key_press(key)
	if (key == bind_to_dik(key_bindings.kWPN_FIRE)) then
		fluid_aim_reset_fire_on_load = false
	end
	if (key == bind_to_dik(key_bindings.kWPN_ZOOM)) then
		if ui_options.get("control/general/aim_toggle") and axr_main.weapon_is_zoomed then
			fluid_aim_toggle = true
		end
	end
end

-- Key release to reset toggle aim release
local function on_key_release(key)
	if (key == bind_to_dik(key_bindings.kWPN_ZOOM)) then
		if ui_options.get("control/general/aim_toggle") then
			fluid_aim_toggle = false
		end
	end
end

-- Prevent fire weapon button state from firing the weapon when dying and loading last save
local function ignore_fire_key_press()
	fluid_aim_reset_fire_on_load = true
end


function on_game_start()
	RegisterScriptCallback("on_key_press", on_key_press)
	RegisterScriptCallback("on_key_release", on_key_release)
	RegisterScriptCallback("actor_on_update",actor_on_update)
	RegisterScriptCallback("actor_on_weapon_jammed",actor_on_weapon_jammed)
	RegisterScriptCallback("on_actor_first_update", ignore_fire_key_press)
	RegisterScriptCallback("on_option_change", ignore_fire_key_press)
end