enum ERemoteDetonatorLEDState
{
	OFF = 0,
	LIT,
}

class RemoteDetonator : Inventory_Base
{
	const string COLOR_LED_OFF 		= "#(argb,8,8,3)color(0,0,0,1.0,co)";
	const string COLOR_LED_LIT 		= "#(argb,8,8,3)color(1,0,0,1.0,co)";
	const string SELECTION_NAME_LED = "LED";

	protected ERemoteDetonatorLEDState m_LastLEDState;
	
	bool IsKit()
	{
		return true;
	}
	
	void UpdateLED(ERemoteDetonatorLEDState pState, bool pForced = false)
	{
		int selectionIdx = GetHiddenSelectionIndex(SELECTION_NAME_LED);

		switch (pState)
		{
		case ERemoteDetonatorLEDState.LIT:
			SetObjectTexture(selectionIdx, COLOR_LED_LIT);
		break;
		default:
			SetObjectTexture(selectionIdx, COLOR_LED_OFF);
		}
		
		m_LastLEDState = pState;
		SetSynchDirty();
	}

	override void SetActions()
	{
		super.SetActions();

		AddAction(ActionAttachExplosivesTrigger);
		AddAction(ActionDisarmExplosiveWithRemoteDetonatorUnpaired);
	}
}

class RemoteDetonatorTrigger : RemoteDetonator
{
	protected const string ANIM_PHASE_TRIGGER = "trigger";
	
	protected bool m_LED;
	protected ref RemotelyActivatedItemBehaviour m_RAIB;
	
	void RemoteDetonatorTrigger()
	{
		m_RAIB = new RemotelyActivatedItemBehaviour(this);		
		m_RAIB.SetTrigger();
		
		RegisterNetSyncVariableInt("m_RAIB.m_PairDeviceNetIdLow");
		RegisterNetSyncVariableInt("m_RAIB.m_PairDeviceNetIdHigh");
		RegisterNetSyncVariableInt("m_LastLEDState", 0, EnumTools.GetEnumSize(ERemoteDetonatorLEDState));
		
		UpdateLED(m_LastLEDState);
	}
	
	override bool IsKit()
	{
		return false;
	}
	
 	override void OnVariablesSynchronized()
    {
        super.OnVariablesSynchronized();

		if (m_RAIB)
		{
			m_RAIB.OnVariableSynchronized();
		}
		
		UpdateLED(m_LastLEDState);
	}
	
	override void EEItemLocationChanged(notnull InventoryLocation oldLoc, notnull InventoryLocation newLoc)
	{
		super.EEItemLocationChanged(oldLoc, newLoc);
		 
		if (m_RAIB)
		{
			m_RAIB.Pair();
		}
	}
	
	override RemotelyActivatedItemBehaviour GetRemotelyActivatedItemBehaviour()
	{
		return m_RAIB;
	}
	
	override void OnCEUpdate()
	{
		super.OnCEUpdate();
		
		if (!IsRuined() && IsConnected() && GetControlledDevice())
		{
			if (vector.DistanceSq(GetPosition(), GetControlledDevice().GetPosition()) <= Math.SqrFloat(UAMaxDistances.EXPLOSIVE_REMOTE_ACTIVATION))
			{
				UpdateLED(ERemoteDetonatorLEDState.LIT);
				
				return;
			}
		}
		
		UpdateLED(ERemoteDetonatorLEDState.OFF);
	}
	
	override void PairRemote(notnull EntityAI trigger)
	{
		m_RAIB.Pair(trigger);
	}
	
	override void UnpairRemote()
	{
		UpdateLED(ERemoteDetonatorLEDState.OFF);
		m_RAIB.Unpair();
	}

	override void OnActivatedByItem(notnull ItemBase item)
	{
		if (GetGame().IsServer())
		{
			if (m_RAIB.IsPaired() && !IsRuined())
			{
				ItemBase device = ItemBase.Cast(GetControlledDevice());
				if (device && vector.DistanceSq(GetPosition(), device.GetPosition()) <= Math.SqrFloat(UAMaxDistances.EXPLOSIVE_REMOTE_ACTIVATION))
				{
					device.OnActivatedByItem(this);
				}
			}
		}
	}
	
	void SetControlledDevice(EntityAI pDevice)
	{
		m_RAIB.Pair(pDevice);
	}

	bool IsConnected()
	{
		return m_RAIB.IsPaired();
	}
	
	EntityAI GetControlledDevice()
	{
		return m_RAIB.GetPairDevice();
	}
	
	static RemoteDetonatorTrigger SpawnInPlayerHands(notnull EntityAI pEntity, EntityAI deviceToPair = null)
	{
		string type = "RemoteDetonatorTrigger";
		RemoteDetonatorTrigger rdt;
		PlayerBase player = PlayerBase.Cast(pEntity);
		if (player)
		{
			ItemBase inHandsItem = player.GetItemInHands();
			if (inHandsItem)
			{
				if (deviceToPair)
				{
					ReplaceDetonatorItemOnArmLambda onArmLambda = new ReplaceDetonatorItemOnArmLambda(inHandsItem, type);
					onArmLambda.SetPairDevice(deviceToPair);
					MiscGameplayFunctions.TurnItemIntoItemEx(player, onArmLambda);
				}
				else
				{
					ReplaceDetonatorItemLambda lambda = new ReplaceDetonatorItemLambda(inHandsItem, type);
					MiscGameplayFunctions.TurnItemIntoItemEx(player, lambda);
				}
				

				rdt = RemoteDetonatorTrigger.Cast(player.GetItemInHands());
			}
			else
				rdt = RemoteDetonatorTrigger.Cast(player.GetHumanInventory().CreateInHands(type));
			
			//! item replaced, use different IK
			if (player.GetItemInHands())
				player.GetItemAccessor().OnItemInHandsChanged();
		}
		
		return rdt;
	}
	
	override void OnAnimationPhaseStarted(string animSource, float phase)
	{
		if (animSource == ANIM_PHASE_TRIGGER)
		{
			if (phase > 0.01)
			{
				UpdateLED(ERemoteDetonatorLEDState.OFF);
			}
		}
	}
	
	override void SetActions()
	{
		super.SetActions();

		RemoveAction(ActionAttachExplosivesTrigger);

		AddAction(ActionAttachOnTrap);
		AddAction(ActionDisarmExplosiveWithRemoteDetonator);
		AddAction(ActionTriggerRemotely);
	}
	
#ifdef DIAG_DEVELOPER
	override protected string GetDebugText()
	{
		string debug_output;
		debug_output += string.Format("low net id: %1\n", m_RAIB.GetPairDeviceNetIdLow());
		debug_output += string.Format("high net id: %1\n", m_RAIB.GetPairDeviceNetIdHigh());
		debug_output += string.Format("pair device: %1\n", m_RAIB.GetPairDevice());
		return debug_output;
	}
#endif
}

class RemoteDetonatorReceiver : RemoteDetonator
{
	void RemoteDetonatorReceiver()
	{
		UpdateLED(ERemoteDetonatorLEDState.OFF, true);
	}
	
	override bool IsKit()
	{
		return false;
	}
	
	override void OnWasDetached(EntityAI parent, int slot_id)
	{
		UpdateLED(ERemoteDetonatorLEDState.OFF);
	}
	
	override void EEKilled(Object killer)
	{
		super.EEKilled(killer);
		
		UpdateLED(ERemoteDetonatorLEDState.OFF, true);
	}

	override void SetActions()
	{
		super.SetActions();
		
		RemoveAction(ActionAttachExplosivesTrigger);
		RemoveAction(ActionDisarmExplosiveWithRemoteDetonatorUnpaired);
	}
}

class ReplaceDetonatorItemLambda : ReplaceItemWithNewLambdaBase
{
	override void CopyOldPropertiesToNew(notnull EntityAI old_item, EntityAI new_item)
	{
		super.CopyOldPropertiesToNew(old_item, new_item);

		MiscGameplayFunctions.TransferItemProperties(old_item, new_item);		
	}
}

class ReplaceDetonatorItemOnArmLambda : ReplaceDetonatorItemLambda
{
	EntityAI m_PairDevice

	void SetPairDevice(EntityAI device)
	{
		m_PairDevice = device;
	}
	
	override void OnSuccess(EntityAI new_item)
	{
		super.OnSuccess(new_item);
		
		RemoteDetonator detonator = RemoteDetonator.Cast(new_item);
		if (detonator)
		{
			ExplosivesBase explosive = ExplosivesBase.Cast(m_PairDevice);
			if (explosive)
			{
				ItemBase receiver = ItemBase.Cast(explosive.GetInventory().CreateAttachment("RemoteDetonatorReceiver"));
				if (receiver)
				{
					MiscGameplayFunctions.TransferItemProperties(detonator, receiver);
					receiver.LockToParent();
					explosive.SetTakeable(false);
					explosive.PairWithDevice(detonator);
					explosive.Arm();
				}
			}
		}
	}
	
	override void OnAbort()
	{
		ExplosivesBase explosive = ExplosivesBase.Cast(m_PairDevice);
		if (explosive)
		{
			explosive.LockTriggerSlots();
			explosive.SetTakeable(true);
		}
	}
}

class ReplaceDetonatorItemOnDisarmLambda : ReplaceDetonatorItemLambda
{
	override void OnSuccess(EntityAI new_item)
	{
		super.OnSuccess(new_item);
		
		RemoteDetonator detonator = RemoteDetonator.Cast(m_OldItem);
		if (detonator)
		{
			if (detonator.GetRemotelyActivatedItemBehaviour())
			{
				ExplosivesBase explosive = ExplosivesBase.Cast(detonator.GetRemotelyActivatedItemBehaviour().GetPairDevice());
				if (explosive)
				{
					explosive.Disarm();
				}
			}
		}
	}
	
	override void OnAbort()
	{
		super.OnAbort();
		
		RemoteDetonator detonator = RemoteDetonator.Cast(m_OldItem);
		if (detonator)
		{
			if (detonator.GetRemotelyActivatedItemBehaviour())
			{
				ExplosivesBase explosive = ExplosivesBase.Cast(detonator.GetRemotelyActivatedItemBehaviour().GetPairDevice());
				if (explosive)
				{
					explosive.LockExplosivesSlots();
				}
			}
		}
	}
}
