using UnityEngine;
using System.Collections;
using System.Linq;

public enum PlayerID
{
	Player1,
	Player2,
	Player3,
	Player4,
}

public enum BaseShipComponents
{
	Engine	= 0,
	Shield	= 1,
	Laser	= 2,
}

[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(Collider2D))]
public class BaseShipComponent : MonoBehaviour 
{
	public string ShipLayerString;
	public int ShipLayer;

	public Sprite Icon;

	//public GameObject JointObject;

	public Transform Children;
	public Hardpoint[] Hardpoints;
	public BaseShipComponent[] HardpointComponents;
	
	public PlayerShip BaseShip;
	
	public BaseShipComponent[] ComponentsList;

	public PlayerID PlayerID;

	[SerializeField]
	protected EnergyBar energyBar;

	[SerializeField]
	protected Rigidbody2D thisRigidbody;
	[SerializeField]
	protected Collider2D thisCollider;
	[SerializeField]
	protected Transform thisTransform;
	protected Material thisMaterial;

	[SerializeField]
	protected InputController inputController;
	protected BuildController buildController;

	protected AudioSource audio;
	public bool LoopAudio;

	void Awake () 
	{
		thisRigidbody = rigidbody2D;
		thisCollider = collider2D;
		thisTransform = transform;

		audio = GetComponent<AudioSource>();
		if(audio != null)
			audio.loop = LoopAudio;

		inputController = FindObjectOfType<InputController> ();
		energyBar = GameObject.Find ("EnergyBar").GetComponent<EnergyBar> ();
		buildController = FindObjectOfType<BuildController> ();

		if (thisTransform.FindChild("Hardpoint") != null)
		{
			GameObject h = thisTransform.FindChild("Hardpoint").gameObject;
			Hardpoints = h.transform.GetComponentsInChildren<Hardpoint>();

			for(int i = 0 ; i < Hardpoints.Length ; i++)
			{
				Hardpoint pt  = Hardpoints[i];
				pt.ID = i;
				pt.Base = this;
			}
		}
		
		if(HardpointComponents.Length == 0)
		{
			HardpointComponents = new BaseShipComponent[Hardpoints.Length];
		}
		
		ShipLayer = LayerMask.NameToLayer(ShipLayerString);

		//if(JointObject == null)
		//	JointObject = Resources.Load("ShipComponents/ShipJoint") as GameObject;
	}
	
	public void AddRandomShipComponent()
	{
		GameObject g = Instantiate(ComponentsList[Random.Range (0, ComponentsList.Length)]) as GameObject;
		if(!AddShipComponent(g.GetComponent<BaseShipComponent>(), Random.Range(0,Hardpoints.Length), (PlayerID) Random.Range(0,4)))
		{
			Destroy(g);	
		}
	}

	private Vector2[] connectedAnchorVectors = new []
	{
		new Vector2( 0.7946f,  0.0318f),
		new Vector2(-0.7861f, -0.0339f),
		new Vector2(-0.7182f, -1.4262f),
		new Vector2( 0.0303f, -1.8035f),
		new Vector2( 0.7182f, -1.4262f)
	};
	
	public virtual bool AddShipComponent(BaseShipComponent component, int hardpointIndex, PlayerID playerID)
	{
		if(HardpointIsValid(hardpointIndex))
		{
			HardpointComponents[hardpointIndex] = component;

			Vector3 pos = Hardpoints[hardpointIndex].HardpointTransform.position;
			Vector3 jPos = Vector3.Lerp(pos, component.transform.position,0.5f);

			Debug.Log ("Adding component at space: " + Hardpoints[hardpointIndex].name + " | Player " + playerID);

			/*GameObject joint = Instantiate(JointObject, jPos, Quaternion.identity) as GameObject;

			Transform jTransform = joint.transform;
			jTransform.SetParent(thisTransform);
			Rigidbody2D jBody = joint.rigidbody2D;

			DistanceJoint2D m_joint = joint.GetComponent<DistanceJoint2D>();
			m_joint.connectedBody = thisTransform.gameObject.rigidbody2D;
			m_joint.collideConnected = true;
			m_joint.distance = 0.15f;
			m_joint.maxDistanceOnly = false;
			m_joint.GetComponent<DistanceJoint2D>().connectedAnchor = connectedAnchorVectors[hardpointIndex];*/

			//component.LockPosition(jBody);
			component.LockPosition(thisRigidbody, hardpointIndex);

			component.transform.SetParent(thisTransform, true);

			component.PlayerID = playerID;

			thisMaterial = component.GetComponentInChildren<MeshRenderer>().material;

			if (thisMaterial != null)
			{
				if (playerID == PlayerID.Player1) thisMaterial.color = Color.blue;
				else if (playerID == PlayerID.Player2) thisMaterial.color = Color.green;
				else if (playerID == PlayerID.Player3) thisMaterial.color = Color.red;
				else if (playerID == PlayerID.Player4) thisMaterial.color = Color.yellow;
			}

			StartCoroutine(Activate());
			
			return true;
		}
		
		return false;
	}

	private Vector2[] connectedComponentVectors = new []
	{
		new Vector2( 0.6180252f, 0.4495832f), 	//TopRight
		new Vector2( 0.0134795f, 1.8190500f), 	//Top
		new Vector2(-0.6180252f, 0.4495832f),	//TopLeft
		new Vector2(-0.7646119f,-0.6127757f),	//MiddleLeft
		new Vector2(-0.7134842f,-1.4317260f),	//BottomLeft
		new Vector2( 0.0187757f,-1.7825600f),	//Bottom
		new Vector2( 0.7134842f,-1.4317260f),	//BottomRight
		new Vector2( 0.7646119f,-0.6127757f)	//MiddleRight
	};

	public void LockPosition(Rigidbody2D parentBody, int index)
	{
		DistanceJoint2D m_joint  = gameObject.AddComponent<DistanceJoint2D>();

		m_joint.connectedBody = parentBody;
		m_joint.collideConnected = true;
		//m_joint.distance = 0.15f;
		m_joint.distance = 0.25f;
		m_joint.connectedAnchor = connectedComponentVectors[index];
		m_joint.maxDistanceOnly = false;

		gameObject.layer = ShipLayer;
		ResetForces();
	}
	
	public void ResetForces()
	{
		thisRigidbody.velocity = Vector3.zero;
		thisRigidbody.angularVelocity = 0;
	}
	
	public bool HardpointIsValid(int hardpoint)
	{
		if(hardpoint >= Hardpoints.Length)
		{
			Debug.Log("Attempting to add illegal hardpoint at index " + hardpoint);
		}
		
		if(HardpointComponents[hardpoint] == null)
		{
			return true;
		}
		
		return false;
	}

	public virtual IEnumerator Activate()
	{
		while (inputController.playersActiveKey[(int) PlayerID])
		{
			//Debug.Log("Component has no activate method!");
			yield return null;
		}
	}

	protected void PlayAudio()
	{
		audio.Play();
	}
	protected void StopAudio()
	{
		audio.Stop();
	}
}
