:NAME gear_manager

:GEAR c_object* UI_object
:GEAR float32 start_time
:GEAR c_object* last_spawned
:GEAR c_object* count_object
:GEAR int32 count
:GEAR int32 actual_count
:GEAR int32 consumable_index

:GLOBAL GEAR noise_maker		-- CB_HACK: Make sure these match the "global_names".
:GLOBAL GEAR zip
:GLOBAL GEAR clone
:GLOBAL GEAR disguise
:GLOBAL GEAR crate
:GLOBAL GEAR freeze
:GLOBAL GEAR shield
:GLOBAL GEAR distract
:GLOBAL GEAR hint
:GLOBAL GEAR store

:GLOBAL uint16 key_count
:GLOBAL uint16 mode
:GLOBAL uint16 desired_mode
:GLOBAL c_object* player_proxy
:GLOBAL float32 mode_start_time
:GLOBAL c_object_placement*	counter_placement
:GLOBAL boolean refresh_iap_counts

k_count_marker_name= "count"
k_ui_time_mode= e_value("e_time_mode", "_time_mode_ui")

k_mode_standard= 0
k_mode_iap= 1

k_1_key= e_value("e_key", "_key_1")
k_2_key= e_value("e_key", "_key_2")
k_3_key= e_value("e_key", "_key_3")
k_4_key= e_value("e_key", "_key_4")
k_5_key= e_value("e_key", "_key_5")

-- ------------------- constants ------------------- 

k_primary_player= e_value("e_player", "_player_primary")

k_noise_maker = { }
k_noise_maker["spawner_name"] = "noise_maker"
k_noise_maker["global_name"] = "noise_maker" -- CB_HACK: There's probably a more elegant solution to this.
k_noise_maker["icon_name"] = "noisemaker_icon"
k_noise_maker["cooldown"] = 5.0
k_noise_maker["forbidden_when_seen"] = true
k_noise_maker["shelf"] = k_mode_standard
k_noise_maker["hotkey"]= k_1_key

k_zip = { }
k_zip["spawner_name"] = "zip"
k_zip["global_name"] = "zip" -- CB_HACK: There's probably a more elegant solution to this.
k_zip["icon_name"] = "zip_icon"
k_zip["cooldown"] = 2.0
k_zip["forbidden_when_seen"] = false
k_zip["shelf"] = k_mode_standard
k_zip["hotkey"]= k_2_key


k_clone = { }
k_clone["spawner_name"] = "clone"
k_clone["global_name"] = "clone" -- CB_HACK: There's probably a more elegant solution to this.
k_clone["icon_name"] = "clone_icon"
k_clone["cooldown"] = 5.0
k_clone["forbidden_when_seen"] = true
k_clone["shelf"] = k_mode_standard
k_clone["hotkey"]= k_3_key

k_disguise = { }
k_disguise["spawner_name"] = "disguise"
k_disguise["global_name"] = "disguise"
k_disguise["icon_name"] = "disguise_icon"
k_disguise["cooldown"] = 5.0
k_disguise["forbidden_when_seen"] = true
k_disguise["shelf"] = k_mode_standard
k_disguise["hotkey"]= k_4_key

k_crate = { }
k_crate["spawner_name"] = "crate"
k_crate["global_name"] = "crate"
k_crate["icon_name"] = "crate_icon"
k_crate["cooldown"] = 1.5
k_crate["forbidden_when_seen"] = false
k_crate["shelf"] = k_mode_standard
k_crate["hotkey"]= k_5_key

k_freeze = { }
k_freeze["spawner_name"] = "freeze"
k_freeze["global_name"] = "freeze"
k_freeze["icon_name"] = "freeze_icon"
k_freeze["cooldown"] = 10
k_freeze["forbidden_when_seen"] = false
k_freeze["consumable_id"]= "freeze"
k_freeze["shelf"] = k_mode_iap
k_freeze["hotkey"]= k_1_key

k_shield = { }
k_shield["spawner_name"] = "shield"
k_shield["global_name"] = "shield"
k_shield["icon_name"] = "shield_icon"
k_shield["cooldown"] = 10
k_shield["forbidden_when_seen"] = false
k_shield["consumable_id"]= "shield"
k_shield["shelf"] = k_mode_iap
k_shield["hotkey"]= k_2_key


k_distract = { }
k_distract["spawner_name"] = "distract"
k_distract["global_name"] = "distract"
k_distract["icon_name"] = "distract_icon"
k_distract["cooldown"] = 2
k_distract["forbidden_when_seen"] = false
k_distract["consumable_id"]= "distract"
k_distract["shelf"] = k_mode_iap
k_distract["hotkey"]= k_3_key

k_hint = { }
k_hint["spawner_name"] = "hint"
k_hint["global_name"] = "hint"
k_hint["icon_name"] = "hint_icon"
k_hint["cooldown"] = 1.5
k_hint["forbidden_when_seen"] = false
k_hint["shelf"] = k_mode_iap


k_store = { }
k_store["spawner_name"] = "store"
k_store["global_name"] = "store"
k_store["icon_name"] = "store_icon"
k_store["cooldown"] = 1.5
k_store["forbidden_when_seen"] = false
k_store["shelf"] = k_mode_iap


k_gear = { }
k_gear[0] = k_noise_maker
k_gear[1] = k_zip
k_gear[2] = k_clone
k_gear[3] = k_disguise
k_gear[4] = k_crate
k_gear[5] = k_freeze
k_gear[6] = k_shield
k_gear[7] = k_distract
k_gear[8] = k_hint
k_gear[9] = k_store

k_mode_standard= 0
k_mode_iap= 1

k_standard_shelf= { }
k_standard_shelf[0] = k_noise_maker
k_standard_shelf[1] = k_zip
k_standard_shelf[2] = k_clone
k_standard_shelf[3] = k_disguise
k_standard_shelf[4] = k_crate

k_iap_shelf= { }
k_iap_shelf[0] = k_freeze
k_iap_shelf[1] = k_shield
k_iap_shelf[2] = k_distract
k_iap_shelf[3] = k_hint
k_iap_shelf[4] = k_store

k_shelves= {}
k_shelves[k_mode_standard]= k_standard_shelf
k_shelves[k_mode_iap]= k_iap_shelf

k_mode_transition_time= 1

-- ------------------- initialization ------------------- 

function gear_state_initialize(gear_state)
	gear_state.UI_object= nil
	gear_state.start_time= -10000  -- CB_HACK:  This is a hack, there should probably be something more elegant.
	gear_state.last_spawned = nil
	gear_state.count_object= nil
	gear_state.count= 0
	gear_state.actual_count= 0
	gear_state.consumable_index= -1
end

function global_initialize(g)

	gear_state_initialize(g.noise_maker)
	gear_state_initialize(g.zip)
	gear_state_initialize(g.clone)
	gear_state_initialize(g.disguise)
	gear_state_initialize(g.crate)
	
	gear_state_initialize(g.freeze)
	gear_state_initialize(g.shield)
	gear_state_initialize(g.distract)
	gear_state_initialize(g.hint)
	gear_state_initialize(g.store)
	
	-- debug: give us some
	--g.freeze.actual_count= 10
	--g.freeze.count= 10
	--g.shield.actual_count= 10
	--g.shield.count= 10
	--g.distract.actual_count= 10
	--g.distract.count= 10
	--g.hint.actual_count= 3
	--g.hint.count= 3
	
	g.key_count= 0
	g.player_proxy= nil
	g.mode= k_mode_standard
	g.desired_mode= k_mode_standard
	g.mode_start_time= -k_mode_transition_time

	g.counter_placement= nil
	g.refresh_iap_counts= false
end


-- ------------------- component ------------------- 

function place_counter(ws, gear_state)
	if (global.counter_placement) then
		local counter= ws.place(global.counter_placement)
		gear_state.count_object= counter
		local marker= gear_state.UI_object.marker_get("count")
		object_attach(gear_state.UI_object, marker, counter, nil)
		counter.hide(true)
	end
end

function refresh_counter(gear_state, count)
	local counter_object= gear_state.count_object
	if (counter_object) then
	
		if (count <= 1) then
			counter_object.hide(true)
		else
			local text= counter_object.text_get()
			if (text) then
				if (count < 100) then
					text.text_set(""..math.floor(count))
				else
					text.text_set("99+")
				end
			end
			
			counter_object.hide(false)
			counter_object.tween_animation_play("changed")
		end
	end
end

function refresh_iap_actual_counts()
	local player_profile= player_profile_get()
	local store= store_get()
	local total_count= 0
	if (player_profile and store) then
		local purchases= player_profile.purchases
		
		for i= 0, #k_iap_shelf do
			local gear_def= k_iap_shelf[i]
			local gear_state = global[gear_def.global_name] -- CB: Find the matching global gear variable.
			if (gear_state.consumable_index~=-1) then
				gear_state.actual_count= purchases.get_consumable_count(gear_state.consumable_index)
				total_count = total_count+gear_state.actual_count
			end
		end
	end
	
	return total_count
end

function start()

	-- place all the iap icons right off the bat
	local ws= world_state_get()
	local w= world_get()
	local hud_plate= w.get_plate("hud")
	local player_profile= player_profile_get()
	local store= store_get()
	local purchases= nil
	if (player_profile) then
		purchases= player_profile.purchases
	end

	global.counter_placement= hud_plate.placement_get("icon_counter")
	
	refresh_iap_actual_counts()
	
	local total_iap_count= 0
	for i= 0, #k_iap_shelf do

		local gear_def= k_iap_shelf[i]
		local gear_state = global[gear_def.global_name] -- CB: Find the matching global gear variable.
		local icon= gear_state.UI_object

		-- set consumable index if appropriate
		if ((gear_def.global_name=="store") and (not store.iaps_enabled())) then
			-- do nothing!
		else
			if (purchases) then
				local item_id= gear_def.consumable_id
				if (item_id) then
					local item= store.item_get_by_id(item_id)
					if (item) then
						gear_state.consumable_index= item.consumable_index
						gear_state.actual_count= purchases.get_consumable_count(gear_state.consumable_index)
						gear_state.count= gear_state.actual_count		-- don't bother playing an animation or sound
						
						total_iap_count = total_iap_count+gear_state.count
					end
				end
			end

			if (not icon) then
				local placement= w.placement_get(gear_def.icon_name)
				if (placement) then
					gear_state.UI_object= ws.place(placement)
					icon= gear_state.UI_object

					if (gear_def.consumable_id) then
						place_counter(ws, gear_state)
						refresh_counter(gear_state, gear_state.actual_count)

						if (gear_state.actual_count<= 0) then
							press(gear_state, true)
						end
					end
					
					-- need to set the count on this guy?
					if (icon) then
						local pos= icon.world_position_get()
						-- whoa! set him out in the middle of nowhere until animation takes over
						icon.position_set(3, pos.y)
					end
				end
			end
		end
	end
	
	-- FOR PC: hide iap icon button if no IAPs
	if (total_iap_count==0) then
		local hudps= hud_plate.plate_state_get()
		local iap_icon= hudps.object_get("iap_icon")
		if (iap_icon) then
			iap_icon.hide(true)
		end
	elseif (player_profile) then

		-- One-time message to point out special powers button
		local campaign_record= player_profile.current_campaign_record_get()
		if (campaign_record and not campaign_record.onetime_message_is_complete(1)) then
		--if (true) then
			local game_hud_zone_ref= w.zone_reference_get("game_hud", false)
			if (game_hud_zone_ref) then
				local game_hud_zone= game_hud_zone_ref.zone
				if (game_hud_zone) then
					local external_ref= game_hud_zone.zone_ref_get("special_powers_tutorial")
					if (external_ref) then
						external_ref.load_as_runtime()
						campaign_record.onetime_message_set_complete(1)
						player_profile.save()
					end
				end
			end
		end
	end
end	

function press(gear, exhaust)
	gear.UI_object.button_press()
	if (exhaust) then
		local button= gear.UI_object.button_get();
		if (button) then
			button.button_enabled_set(false)
		end
	end
end

function unexhaust(gear)
	local button= gear.UI_object.button_get();
	if (button) then
		button.button_enabled_set(true)
	end
end

function set_gear_mode(mode)
	local ws= world_state_get()
	local time= ws.master_time.time
	if ((mode ~= global.mode) and ((time - global.mode_start_time) >= k_mode_transition_time)) then

		-- transition out any icons in the current shelf
		local current_shelf= k_shelves[global.mode]
		for i= 0, #current_shelf do

			local gear_def= current_shelf[i]
			local gear_state = global[gear_def.global_name] -- CB: Find the matching global gear variable.
			local icon= gear_state.UI_object

			if (icon) then
				icon.tween_animation_play_after_delay("slide_out", i*0.1)
			end
		end

		local next_shelf= k_shelves[mode]
		for i= 0, #next_shelf do
			local gear_def= next_shelf[i]
			local gear_state = global[gear_def.global_name] -- CB: Find the matching global gear variable.
			local icon= gear_state.UI_object
			if (icon) then
				-- note, 0.33 is the lengh of the "slide in/out" animation. 
				-- in other words, give the equivalent icon on the other shelf the time to slide out before sliding in
				icon.tween_animation_play_after_delay("slide_in", 0.3+i*0.1)
			end
		end
	
		global.mode= mode
		global.mode_start_time= time
	end
end


function update()
	local w= world_get()
	local ws= world_state_get()
	
	local primary_player= ws.primary_player_get()
	local player= primary_player
	local keyboard= keyboard_get()
	
	if (global.player_proxy) then
		player= global.player_proxy
	end
	
	if (global.refresh_iap_counts) then
		refresh_iap_actual_counts()
		global.refresh_iap_counts= false
	end
	
	if(player) then
		for i=0, #k_gear do

			local gear_def= k_gear[i]
			local gear_state = global[gear_def.global_name] -- CB: Find the matching global gear variable.
			
			if(gear_state.UI_object) then

				local ws= world_state_get()
				local time= ws.time.time			-- CB: Get the time.	
				
				-- check for a tap of the icon
				-- because we run in "UI time", make sure we are explicitly not checking for taps when the game is paused
				if(	(not ws.game_is_paused()) and 
					(time >= gear_state.start_time + gear_def.cooldown) and
					(gear_state.actual_count>0)) then
					
					local allowed= false
				   
					-- CB: Detect to see if the gear has been tapped by the player.
					local input= gear_state.UI_object.input_get()
					if (input and input.get_touch_started()>=0) then
						allowed= true
					elseif (keyboard and gear_def.shelf==global.mode and keyboard.pressed[gear_def.hotkey]) then
						allowed= true
					end

					if (allowed) then
						
						-- some gears are not allowed to be deployed when the player is visible to the NPCs
						if (gear_def.forbidden_when_seen) then

							local target= player.target_get()
							if (target and target.is_immediate()) then
								press(gear_state, false)
								allowed= false

								local player_control= player._c.player_control
								if (player_control) then
									player_control.invalid_gear_ping_pending= true
								end
							end
						end
						
						if (allowed and gear_def.consumable_id) then
							local player_profile= player_profile_get()
							if (player_profile) then
								allowed= player_profile.purchases.use_consumable(gear_state.consumable_index, false)
							else
								allowed= false
							end
						end

						if (allowed) then
							local spawner= primary_player.spawn_get(gear_def.spawner_name)
							if (spawner) then
							
								-- ATTENTION: we are grabbing the spawner off of our primary player, i.e. the 
								-- Rothko object
								-- However, we may be disguised, or there might be a separate "control player".
								-- So we are using the spawner off of the primary player but spawning ON the control player.
								-- this avoids the necessity of duplicating spawners on every potential control object

								gear_state.last_spawned = spawner.spawn_on_object(player)
								gear_state.actual_count = gear_state.actual_count - 1
								
								press(gear_state, gear_state.actual_count == 0)
							
								-- use one up
								if (gear_def.consumable_id) then
									local player_profile= player_profile_get()
									if (player_profile) then
										if (player_profile.purchases.use_consumable(gear_state.consumable_index, true)) then
											player_profile.save()
										else
											print("ERROR: player_profile.use_consumable return true before but false now")
										end
									end
								end

								if(gear_def.cooldown ~= 0) then
									gear_state.start_time = time
								end							
							end
						end
					end
				end
				
			elseif(gear_state.actual_count > 0) then -- CB: If there were previously 0, and now there's not.
				local placement= w.placement_get(gear_def.icon_name)
				if (placement) then
					local icon= ws.place(placement)
					gear_state.UI_object= icon
					if (icon) then
						-- make sure we're on the correct current shelf
						if (global.mode == gear_def.shelf) then
							icon.tween_animation_play("slide_in")
						else
							-- place it off-screen somewhere
							local pos= icon.world_position_get()
							icon.position_set(2, pos.y)
						end
					end
					gear_state.count= 1
					place_counter(ws, gear_state)

					-- play pick up sound
					ws.sound_manager.play_sound_by_name("loot_aquired", k_ui_time_mode)
				else
					print("CB_pseudo_assert: gear_manager was looking for a placement named " .. gear_def.icon_name .. " and could not find it")			
				end
			end

			if (gear_state.UI_object) then
				local actual_count= gear_state.actual_count

				-- gear_state.count represents the UI state of the count
				if (gear_state.count ~= actual_count) then

					if (actual_count > gear_state.count) then
						-- play pick up sound
						ws.sound_manager.play_sound_by_name("loot_aquired", k_ui_time_mode)
					end

					if ((actual_count >= 1) and (gear_state.count==0)) then
						unexhaust(gear_state)
					end
					
					refresh_counter(gear_state, actual_count)
					
					gear_state.count= actual_count
				
				end
			
			end
		end
	end
	
	-- possibly update the shelf?
	if (global.mode ~= global.desired_mode) then
		set_gear_mode(global.desired_mode)
	end
end

-- callback from the store
function purchase_complete(bundle, successful)
	if (successful) then
		global.refresh_iap_counts= true
	else
		local notification= world_state_get().place_by_plate("notification", "purchase_fail_notification")
		if (notification) then
			local text= notification.text_get()
			if (text) then
				text.append(bundle.name)
			end
		end
	end
end


system_register(start, update, nil, nil)

event_register(purchase_complete, e_value("e_script_event", "_script_event_purchase_complete"))
event_register(player_rewarded, e_value("e_script_event", "_script_event_campaign_reward"))
