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

public class WaveLogic : MonoBehaviour , IEventHandler
{
    [SerializeField]
    int maxCustomers;
    [SerializeField]
    GameObject NPCPrefab;

    public List<GameObject> customer;

    private float prevTime;
    private bool newWave;
    private int waveSize;
    private int groupNum;

    private int customerNumber;

    // Use this for initialization
    void Start () {
        EventBroadcaster.registerHandler<PlayerWave>(this);

        Random.InitState((int)System.DateTime.Now.Ticks);

        customer = new List<GameObject>();
        prevTime = -5;
        newWave = true;
        waveSize = 0;
        groupNum = 0;
        customerNumber = 0;
    }

    void OnDisable()
    {
        EventBroadcaster.unregsterHandler(this);
    }

	// Update is called once per frame
	void Update () {
		if (Globals.WaveMax <= Globals.GroupNum) {
            if (customer.Count <= 0)
            {
                EventBroadcaster.broadcastEvent(new SurvivedGame());
            }
			return;
		}

		if (0 >= waveSize)
        {
            ++Globals.GroupNum;
            newWave = true;
            groupNum = 0;
        }

        if (newWave)
        {
            newWave = false;
            waveSize = Random.Range(Globals.GroupMin, Globals.GroupMax);
        }

        if (Time.time > (prevTime + Globals.SpawnDelta[Globals.GroupNum - 1]))
        {
            int spawnSize = (((waveSize / (6 - ((5 < groupNum) ? 5 : groupNum++))) < 3) ? ((15 < waveSize) ? waveSize - 15: Random.Range(Globals.SpawnMin, Globals.SpawnMax)) : 3);
            waveSize -= spawnSize;

            int spawn = Random.Range(0, 100) % 3;
            for (int i = 0; i < spawnSize; ++i)
            {
                customer.Add(Instantiate(NPCPrefab, Vector3.zero, Quaternion.Euler(0, -180, 0)));
                customer[customer.Count - 1].GetComponent<WalkToDoor>().spawnPoint = (spawn + i) % 3;
                customer[customer.Count - 1].GetComponent<WalkToDoor>().customerNumber = customerNumber++;
            }
            prevTime = Time.time;
        }
    }

    public void handleEvent(IGameEvent evt)
    {
        customer = customer.OrderBy(c => c.GetComponent<WalkToDoor>().currentRank).ThenBy(c => c.GetComponent<WalkToDoor>().customerNumber).ToList();

        Debug.Log("ARRAY SORT");
        for (int i = 0; i < customer.Count; ++i)
        {
            Debug.Log("Rank: " + customer[i].GetComponent<WalkToDoor>().currentRank + " | Number: " + customer[i].GetComponent<WalkToDoor>().customerNumber);
        }
        Debug.Log("ARRAY SORT");

        PlayerWave myEvent = evt as PlayerWave;

        if (1 == customer.Count)
        { 
            if (customer[0].GetComponent<WalkToDoor>().inTheZone && !customer[0].GetComponent<WalkToDoor>().scored)
            {
                customer[0].GetComponent<WalkToDoor>().GenerateScore(myEvent.strength);
                return;
            }
            else
            {
                return;
            }
        }

        for (int rules = 0; rules < 3; ++rules)
        {
            for (int i = 0; i < customer.Count; ++i)
            {
                var currCust = customer[i].GetComponent<WalkToDoor>();

                if (!currCust.inTheZone || currCust.scored)
                {
                    continue;
                }

                switch (rules)
                {
                    case 0:
                        if (currCust.currentRank == myEvent.strength)
                        {
                            currCust.GenerateScore(myEvent.strength);
                            return;
                        }
                        break;
                    case 1:
                        int prevCustIdx = -1;
                        for (int j = (0 <= (i - 1) ? i - 1 : 0); j >= 0; --j)
                        {
                            if (customer[j].GetComponent<WalkToDoor>().inTheZone && !customer[j].GetComponent<WalkToDoor>().scored)
                            {
                                prevCustIdx = j;
                                break;
                            }
                        }

                        if (currCust.currentRank > myEvent.strength)
                        {
                            if (0 <= prevCustIdx)
                            {
                                var prevCust = customer[prevCustIdx].GetComponent<WalkToDoor>();
                                if (prevCust.currentRank < myEvent.strength)
                                {
                                    prevCust.GenerateScore(myEvent.strength);
                                    return;
                                }
                            }
                            else
                            {
                                currCust.GenerateScore(myEvent.strength);
                                return;
                            }
                        }
                        break;
                    case 2:
                        if (currCust.currentRank > myEvent.strength)
                        {
                            currCust.GenerateScore(myEvent.strength);
                            return;
                        }
                        break;
                    default:
                        break;
                }
            }
        }

        for (int i = customer.Count - 1; i >= 0; --i)
        {
            if (customer[i].GetComponent<WalkToDoor>().inTheZone && !customer[i].GetComponent<WalkToDoor>().scored)
            {
                customer[i].GetComponent<WalkToDoor>().GenerateScore(myEvent.strength);
                return;
            }
        }
    }
}
