using UnityEngine;
using System.Collections;

public class Manager : MonoBehaviour {
    [SerializeField]
    UnityEngine.UI.Image[] plates;

    [SerializeField]
    UnityEngine.UI.Image[] forks;

    [SerializeField]
    UnityEngine.UI.Slider SimSpeed;

    UnityEngine.UI.Text deadlockText;
    bool deadlocked = false;
    UnityEngine.UI.Toggle deadlockPrevention;

	// Use this for initialization
	void Start () {
        deadlockPrevention = transform.FindChild("CanDeadlock").GetComponent<UnityEngine.UI.Toggle>();
        deadlockText = transform.FindChild("DeadlockText").GetComponent<UnityEngine.UI.Text>();
        Reset();
        for (int i = 0; i < 5; i++)
            StartCoroutine(Philosopher(i));
	}
	
	// Update is called once per frame
	void Update () {
        
        if (
        (forks[0].color == Color.magenta &&
        forks[1].color == Color.red &&
        forks[2].color == Color.blue &&
        forks[3].color == Color.green &&
        forks[4].color == Color.yellow)
        ||
        (forks[0].color == Color.red &&
        forks[1].color == Color.blue &&
        forks[2].color == Color.green &&
        forks[3].color == Color.yellow &&
        forks[4].color == Color.magenta))
        {
            deadlocked = true;
            deadlockText.enabled = true;
        }
	}

    public void Reset(){
        deadlocked = false;
        deadlockText.enabled = false;
        plates[0].color = Color.red;

        plates[1].color = Color.blue;
        plates[2].color = Color.green;
        plates[3].color = Color.yellow;
        plates[4].color = Color.magenta;
        for (int i = 0; i < 5; i++)
        {
            forks[i].color = Color.white;
            plates[i].transform.GetChild(0).GetComponent<UnityEngine.UI.Image>().enabled = false;
        }


    }

    //0 Left:1 Right: 0
    //1 Left:2 Right: 1
    //2 Left:3 Right: 2 
    //3 Left:4 Right: 3
    //4 Left:0 Right: 4
    
    IEnumerator Philosopher(int id)
    {
        while (true)
        {
            float thinkTime = Random.Range(1f / SimSpeed.value, 4f / SimSpeed.value);
            yield return new WaitForSeconds(thinkTime);
            if (deadlockPrevention.isOn)
            {
                if (PickupFork(id, "Left"))
                    if (!PickupFork(id, "Right"))
                        PutdownFork(id, "Left");
            }
            else
            {
                PickupFork(id, "Left");
                PickupFork(id, "Right");
            }
            //Try to pickup the forks
            //PickupFork(id, "Left");
            //PickupFork(id, "Right");
            if (CanEat(id))
            {
                plates[id].transform.GetChild(0).GetComponent<UnityEngine.UI.Image>().enabled = true;
                float eatTime = Random.Range(1f / SimSpeed.value, 4f / SimSpeed.value);
                yield return new WaitForSeconds(eatTime);
                plates[id].transform.GetChild(0).GetComponent<UnityEngine.UI.Image>().enabled = false;
                PutdownFork(id, "Left");
                PutdownFork(id, "Right");
            }

        }
    }

    public bool CanEat(int plate)
    {
        switch (plate)
        {
            case 0:
                //fork = afork == "Left" ? fork = 1 : fork = 0;
                if (forks[1].color == plates[plate].color && forks[0].color == plates[plate].color)
                    return true;
                return false;
            case 1:
                //fork = afork == "Left" ? fork = 2 : fork = 1;
                if (forks[2].color == plates[plate].color && forks[1].color == plates[plate].color)
                    return true;
                return false;
            case 2:
                //fork = afork == "Left" ? fork = 3 : fork = 2;
                if (forks[3].color == plates[plate].color && forks[2].color == plates[plate].color)
                    return true;
                return false;
            case 3:
                //fork = afork == "Left" ? fork = 4 : fork = 3;
                if (forks[4].color == plates[plate].color && forks[3].color == plates[plate].color)
                    return true;
                return false;
            case 4:
                //fork = afork == "Left" ? fork = 0 : fork = 4;
                if (forks[0].color == plates[plate].color && forks[4].color == plates[plate].color)
                    return true;
                return false;
        }
        return false;
    }
    public bool PickupFork(int plate, string afork){
        int fork = 0;
        switch (plate) {
            case 0:
                fork = afork == "Left" ? fork = 1 : fork = 0;
                if (forks[fork].color != Color.white) return false; else forks[fork].color = plates[plate].color;
                break;
            case 1:
                fork = afork == "Left" ? fork = 2 : fork = 1;
                if (forks[fork].color != Color.white) return false; else forks[fork].color = plates[plate].color;
                break;
            case 2:
                fork = afork == "Left" ? fork = 3 : fork = 2;
                if (forks[fork].color != Color.white) return false; else forks[fork].color = plates[plate].color;
                break;
            case 3:
                fork = afork == "Left" ? fork = 4 : fork = 3;
                if (forks[fork].color != Color.white) return false; else forks[fork].color = plates[plate].color;
                break;
            case 4:
                fork = afork == "Left" ? fork = 0 : fork = 4;
                if (forks[fork].color != Color.white) return false; else forks[fork].color = plates[plate].color;
                break;
        }
        return true;
    }

    public bool PutdownFork(int plate, string afork)
    {
        int fork = 0;
        switch (plate)
        {
            case 0:
                fork = afork == "Left" ? fork = 1 : fork = 0;
                if (forks[fork].color == plates[plate].color) { forks[fork].color = Color.white; return true; } return false;
            case 1:
                fork = afork == "Left" ? fork = 2 : fork = 1;
                if (forks[fork].color == plates[plate].color) { forks[fork].color = Color.white; return true; } return false;
            case 2:
                fork = afork == "Left" ? fork = 3 : fork = 2;
                if (forks[fork].color == plates[plate].color) { forks[fork].color = Color.white; return true; } return false;
            case 3:
                fork = afork == "Left" ? fork = 4 : fork = 3;
                if (forks[fork].color == plates[plate].color) { forks[fork].color = Color.white; return true; } return false;
            case 4:
                fork = afork == "Left" ? fork = 0 : fork = 4;
                if (forks[fork].color == plates[plate].color) { forks[fork].color = Color.white; return true; } return false;
        }
        return false;
    }
}