using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class BaseCell : MonoBehaviour {
	public List<CellConnection> possibleConnections;
	public bool canMove = false;
	public bool canEat = false;

	[HideInInspector] [SerializeField] Rigidbody2D rig;
	private float movementSpeed = 10f;
    public Action onStructureChange;

    [NonSerialized]
    public HeadController headController;

    [SerializeField] GameObject foodPrefab;

    public delegate void FoodConsumeDelegate();
    public event FoodConsumeDelegate onFoodConsumed;

	void OnValidate()
	{
        if (!rig)
		    rig = GetComponent<Rigidbody2D> ();
	}


    public void MoveTowards(Vector2 direction)
    {
        if (canMove) {
            rig.AddForce (direction * movementSpeed, ForceMode2D.Force);
        }
        foreach (var c in possibleConnections)
        {
            if (c.cell != null)
                c.cell.MoveTowards(direction);
        }
    }

    public void GetAllOpenCells(ref List<BaseCell> cells)
    {
        bool added = false;
        foreach (var c in possibleConnections)
        {
            if (c.cell == null && !added)
            {
                cells.Add(this);
                added = true;
            }
            if (c.cell != null)
                c.cell.GetAllOpenCells(ref cells);
        }
    }

    public void Rotate(Vector2 centerOfMass, float amount)
    {
        if (canMove)
        {
            var diff = (centerOfMass - (Vector2)transform.position).normalized;
            rig.AddForce(new Vector2(-diff.y,diff.x)*amount);
        }
        foreach (var c in possibleConnections)
        {
            if (c.cell != null)
                c.cell.Rotate(centerOfMass,amount);
        }
    }

    public void CalculatePositionsAndMass(ref float mass, ref Vector2 positions, ref int count)
    {
        positions += (Vector2)transform.position;
        mass += rig.mass;
        count ++;
        foreach (var c in possibleConnections)
        {
            if (c.cell != null)
            {
                c.cell.CalculatePositionsAndMass(ref mass,ref positions, ref count);
            }
        }
    }

	public void OnCollisionEnter2D(Collision2D coll)
	{
        if (coll.gameObject.tag == "Death")
        {
            if (coll.gameObject.GetComponent<HeadController>() == headController)
                return;

            if (!coll.gameObject.GetComponent<BaseCell>().enabled)
                return;
            foreach (var c in GetComponents<Joint2D>())
            {
                Destroy(c);
            }
            OnBreakOff();
            BreakOffChildren();
            onStructureChange();
        }
		if (!canEat)
			return;
		var food = coll.gameObject.GetComponent<Food> ();
		if (food != null)
		{
		    headController.AddNutrition();
            food.Consume();
		    if (onFoodConsumed != null)
		        onFoodConsumed();
		}
	}

    void OnJointBreak2D(Joint2D brokenJoint)
    {
        var brokenOffCell = brokenJoint.connectedBody.GetComponent<BaseCell>();
        brokenOffCell.OnBreakOff();
        for (int i = 0; i < possibleConnections.Count; i++)
        {
            var connection = possibleConnections[i];
            if (connection.cell == brokenOffCell)
            {
                connection.cell = null;
                break;
            }
        }
        onStructureChange();
    }

    void BreakOffChildren()
    {
        for (int i = 0; i < possibleConnections.Count; i++)
        {
            var connection = possibleConnections[i];
            if (connection.cell)
            {
                connection.cell.OnBreakOff();
                connection.cell = null;
            }
        }
    }

    void OnBreakOff()
    {
        BreakOffChildren();
        enabled = false;
        GetComponent<SpriteRenderer>().color = Color.red;
        StartCoroutine(Death());
    }

    IEnumerator Death()
    {
        yield return new WaitForSeconds(10);
        Instantiate(foodPrefab, transform.position, Quaternion.identity);
        Destroy(gameObject);
    }
        
    public void GrowCell(CellConnection connection, GameObject neoCell)
	{
        headController.UseNutrition();
        var instance = Instantiate (neoCell, connection.transform.position, connection.transform.rotation);
	    var instanceRigidbody = instance.GetComponent<Rigidbody2D>();
        instanceRigidbody.velocity = rig.velocity;
        connection.cell = instance.GetComponent<BaseCell> ();
        connection.cell.onStructureChange = onStructureChange;
        connection.cell.headController = headController;
        var hinge = gameObject.AddComponent<FrictionJoint2D>();
        hinge.connectedBody = instanceRigidbody;
        //hinge.useLimits = true;
        var limits = new JointAngleLimits2D();
        limits.max = 135;
        //hinge.limits = limits;
        hinge.maxForce = 75f;
        hinge.maxTorque = 10f;
        hinge.breakForce = 50f;
        hinge.breakTorque = 50f;
        onStructureChange();
	}
}