using System.Collections.Generic;
using UnityEngine;

namespace Assets.Scripts
{
    // Generates game basically
    public class LaneManagerScript : MonoBehaviour
    {
        public int LaneCount;

        public float SpawnRateMax;
        private float[] _spawnTimer;
        private float[] _spawnRateSet;
        private float[] _spawnRateRand;

        public float GoodOdds;
        public float PowerUpOdds;

        public int GoodTypes;
        public int BadTypes;
        public int PowerUpTypes;

        private bool[] _direcionIsLeft;

        // TESTING VALUES
        public Vector2 LaneWorldPos;
        public float XFlipDistance;
        public float ZSpacing;

        //public enum DataType { Cat, Email, Shopping, Like, Worm, Spam, Trojan, Malware, Bullet, DataShield, Firewall };
        public GameObject[] DataPrefabs;
        private List<GameObject> _dataObjects;

        public GameObject DespawnerPrefab;
        private List<GameObject> _despawnerObjects;

        void Awake()
        {
            _despawnerObjects = new List<GameObject>();

            var newDespawner = (GameObject)Instantiate(DespawnerPrefab, new Vector3(LaneWorldPos.x - 1.5f, LaneWorldPos.y, LaneCount), Quaternion.identity);
            newDespawner.transform.localScale = new Vector3(1.0f, 1.0f, LaneCount + ZSpacing * LaneCount);
            _despawnerObjects.Add(newDespawner);

            newDespawner = (GameObject)Instantiate(DespawnerPrefab, new Vector3(LaneWorldPos.x + XFlipDistance + 1.5f, LaneWorldPos.y, LaneCount), Quaternion.identity);
            newDespawner.transform.localScale = new Vector3(1.0f, 1.0f, LaneCount + ZSpacing * LaneCount);
            _despawnerObjects.Add(newDespawner);

            _dataObjects = new List<GameObject>();

            _direcionIsLeft = new bool[LaneCount];

            // Set default values
            for (int i = 0; i < LaneCount; i++)
            {
                _direcionIsLeft[i] = true;
            }

            _spawnTimer = new float[LaneCount];
            _spawnRateSet = new float[LaneCount];
            _spawnRateRand = new float[LaneCount];

            for (int i = 0; i < LaneCount; i++)
            {
                _spawnRateSet[i] = ((SpawnRateMax / LaneCount) * (i + 1));
            }

            for (int i = 0; i < LaneCount; i++)
            {
                _spawnRateRand[i] = _spawnRateSet[Random.Range(0, LaneCount)];
            }
        }

        // Use this for initialization
        void Start()
        {
            FlipBoard();
        }

        // Update is called once per frame
        void Update()
        {
            for (int j = 0; j < LaneCount; j++)
            {
                if (_spawnTimer[j] >= _spawnRateRand[j])
                {
                    bool isSafe = false;
                    bool[] isGood = new bool[LaneCount];
                    bool[] isLeft = new bool[LaneCount];

                    for (int i = 0; i < LaneCount; i++)
                    {
                        if (i == j)
                        {
                            // Data type
                            float threshold = Random.Range(0.0f, 1.0f);
                            isGood[i] = true;

                            if (threshold > GoodOdds)
                            {
                                isGood[i] = false;
                                isSafe = true;
                            }

                            // Direction management
                            isLeft[i] = true;

                            if (_direcionIsLeft[i] == false)
                            {
                                isLeft[i] = false;
                            }
                        }
                    }

                    if (isSafe)
                    {
                        for (int i = 0; i < LaneCount; i++)
                        {
                            if (i == j)
                            {
                                SpawnData(isGood[i], isLeft[i], i);
                            }
                        }
                    }
                    else
                    {
                        int safeGuard = Random.Range(0, LaneCount);

                        for (int i = 0; i < LaneCount; i++)
                        {
                            if (i == j)
                            {
                                if (i != safeGuard)
                                {
                                    SpawnData(isGood[i], isLeft[i], i);
                                }
                                else
                                {
                                    SpawnData(false, isLeft[i], i);
                                }
                            }
                        }
                    }
                    _spawnTimer[j] -= _spawnRateRand[j];
                    _spawnRateRand[j] = _spawnRateSet[Random.Range(0, LaneCount)];
                }

                _spawnTimer[j] += Time.deltaTime;
            }

            /*
        {
            bool isSafe = false;
            bool[] isGood = new bool[laneCount];
            bool[] isLeft = new bool[laneCount];

            for (int i = 0; i < laneCount; i++)
            {
                // Data type
                float threshold = Random.Range(0.0f, 1.0f);
                isGood[i] = true;

                if (threshold > goodOdds)
                {
                    isGood[i] = false;
                    isSafe = true;
                }

                // Direction management
                isLeft[i] = true;

                if (_direcionIsLeft[i] == false)
                {
                    isLeft[i] = false;
                }
            }

            if (isSafe)
            {
                for (int i = 0; i < laneCount; i++)
                {
                    SpawnData(isGood[i], isLeft[i], i);
                }
            }
            else
            {
                int safeGuard = Random.Range(0, laneCount);

                for (int i = 0; i < laneCount; i++)
                {
                    if (i != safeGuard)
                    {
                        SpawnData(isGood[i], isLeft[i], i);
                    }
                    else
                    {
                        SpawnData(false, isLeft[i], i);
                    }
                }
            }

            _spawnTimer -= spawnRate;
        }

        _spawnTimer += Time.deltaTime;
        */
        }

        void SpawnData(bool isGood, bool isLeft, int laneId)
        {
            GameObject newData;

            int typeHelper;
            if (isGood == false)
            {
                typeHelper = Random.Range(0, BadTypes);
                typeHelper += GoodTypes;

                float threshold = Random.Range(0.0f, 1.0f);

                if (threshold > PowerUpOdds)
                {
                    int powerUpType = Random.Range(0, PowerUpTypes);
                    typeHelper = GoodTypes + BadTypes + powerUpType;
                }
            }
            else
            {
                typeHelper = Random.Range(0, GoodTypes);
            }

            if (isLeft)
            {
                newData = (GameObject)Instantiate(DataPrefabs[typeHelper], new Vector3(LaneWorldPos.x, LaneWorldPos.y, (float)laneId + (laneId * ZSpacing)), Quaternion.identity);
                //newData.transform.localRotation = new Quaternion(0.0f, 0.0f, 0.0f, 0.0f);
                newData.transform.parent = gameObject.transform;
            }
            else
            {
                newData = (GameObject)Instantiate(DataPrefabs[typeHelper], new Vector3(LaneWorldPos.x + XFlipDistance, LaneWorldPos.y, (float)laneId + (laneId * ZSpacing)), Quaternion.identity);
                // newData.transform.localScale = new Vector3(1.0f, 1.0f, -1.0f);
                newData.transform.parent = gameObject.transform;
            }

            _dataObjects.Add(newData);

            _dataObjects[_dataObjects.Count - 1].GetComponent<DataScript>().InitData(isLeft, laneId);
      
        }

        public void FlipTrackDirection(int laneNumber)
        {
            _direcionIsLeft[laneNumber] = !_direcionIsLeft[laneNumber];

            DataScript[] dataObjects;
            dataObjects = FindObjectsOfType<DataScript>();

            foreach (DataScript dataObject in dataObjects)
            {
                dataObject.SwapTrack(laneNumber);
            }
        }

        public void FlipBoard()
        {
            for (int i = 0; i < LaneCount; i++)
            {
                FlipTrackDirection(i);
            }
        }
    }
}
