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

public class GameController : MonoBehaviour {

    [SerializeField]
    Camera raycam;

    [SerializeField]
    GameObject currentClick;
    [SerializeField]
    GameObject lastClick;

    [SerializeField]
    Transform elements;

    GameObject empty;

    Vector3 current;
    Vector3 last;

    bool swap = false;
    bool canSwap = true;

    List<List<int>> rows = new List<List<int>>();
    List<List<int>> columns = new List<List<int>>();

    List<List<GameObject>> rowsTrans = new List<List<GameObject>>();
    List<List<GameObject>> columnsTrans = new List<List<GameObject>>();

    [SerializeField]
    LayerMask mask;

    [SerializeField]
    ElementGenerator eleGenerator;

    Combat combat;

    void Awake()
    {
        empty = new GameObject();
        combat = FindObjectOfType<Combat>();
    }

    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            Vector2 worldPoint = raycam.ScreenToWorldPoint(Input.mousePosition);

            RaycastHit2D hit = Physics2D.Raycast(worldPoint, Vector2.zero, 15f, mask);

            if (hit)
            {                
                if(currentClick == null && canSwap)
                {
                    currentClick = hit.collider.gameObject;
                }
                else
                {
                    if (canSwap)
                    {
                        lastClick = currentClick;
                        currentClick = hit.collider.gameObject;
                    }
                }

                if (currentClick != lastClick && lastClick != null && canSwap && Vector3.Distance(currentClick.transform.position, lastClick.transform.position) <= 2f)
                {
                    if (elements.childCount >= 36)
                    {
                        int count = 0;
                        foreach (Transform trans in elements)
                        {
                            if (trans.GetComponent<ElementLocation>().inGridTrue)
                                count++;


                            if (count >= 36)
                            {
                                current = currentClick.transform.position;
                                last = lastClick.transform.position;

                                canSwap = false;

                                foreach (Transform asd in elements)
                                {
                                    asd.GetComponent<Rigidbody2D>().isKinematic = true;
                                }
                                swap = true;
                            }
                        }
                    }

                    
                    

                }
            }

            
        }

        if(swap)
        {
           ChangeElementsPosition();
        }
        if (canSwap)
        {
            if (elements.childCount >= 36)
            {
                int count = 0;
                foreach (Transform trans in elements)
                {
                    if (trans.GetComponent<ElementLocation>().inGridTrue)
                        count++;


                    if (count >= 36)
                        CheckGrid();
                }
            }
        }

    }

    void ChangeElementsPosition()
    {
        Vector3 pos = Vector3.MoveTowards(currentClick.transform.position, last, Time.deltaTime * 4);
        currentClick.transform.position = pos;

        Vector3 pos2 = Vector3.MoveTowards(lastClick.transform.position, current, Time.deltaTime * 4);
        lastClick.transform.position = pos2;

        if (Vector3.Distance(currentClick.transform.position, last) < 0.001f && Vector3.Distance(lastClick.transform.position, current) < 0.001f)
        {

            CheckGrid();


            lastClick = null;
            currentClick = null;
            swap = false;
            /*
            foreach (Transform trans in elements)
            {
                trans.GetComponent<Rigidbody2D>().isKinematic = false;
            }
            */
        }
    }

    void CheckGrid()
    {
        bool row = false;
        bool column = false;

        for (int i = 0; i < 6; i++)
        {
            List<int> emptyList = new List<int>();
            List<int> emptyList2 = new List<int>();

            for(int j = 0; j < 6; j++)
            {
                emptyList.Add(9);
            }

            for (int j = 0; j < 6; j++)
            {
                emptyList2.Add(9);
            }


            rows.Add(emptyList);
            columns.Add(emptyList2);

            List<GameObject> tmpRow = new List<GameObject>();
            List<GameObject> tmpColumn = new List<GameObject>();

            
            for (int j = 0; j < 6; j++)
            {
                tmpRow.Add(empty);
            }

            for (int j = 0; j < 6; j++)
            {
                tmpColumn.Add(empty);
            }

            rowsTrans.Add(tmpRow);
            columnsTrans.Add(tmpColumn);
        }

        foreach (Transform trans in elements)
        {
            int row_i = trans.GetComponent<ElementLocation>().row - 1;
            int column_i = trans.GetComponent<ElementLocation>().column - 1;

            if (row_i < 0)
                row_i = 6;
            if (column_i < 0)
                column_i = 6;

            List<int> tempRow = rows[row_i];
            List<int> tempColumn = columns[column_i];

            List<GameObject> tmpRow = rowsTrans[row_i];
            List<GameObject> tmpColumn = columnsTrans[column_i];

            int number = System.Convert.ToInt32(trans.gameObject.name);

            tempRow[column_i] = number;
            tempColumn[row_i] = number;

            tmpRow[column_i] = trans.gameObject;
            tmpColumn[row_i] = trans.gameObject;
            
            rows[row_i] = tempRow;
            columns[column_i] = tempColumn;

            rowsTrans[row_i] = tmpRow;
            columnsTrans[column_i] = tmpColumn;
        }

        List<GameObject> rowDestruction = new List<GameObject>();
        List<GameObject> columnDestruction = new List<GameObject>();

        for (int i = 0; i < 6; i++)
        {
            bool combo = false;

            List<int> tmpRow = rows[i];
            List<GameObject> tempRow = rowsTrans[i];

            List<GameObject> objsToDestroyRow = new List<GameObject>();
            objsToDestroyRow.Clear();
            

            int counter = 0;
            int last = 0;

            int eleCount = 0;

            int k = 0;
            string tmpName = "";
            //print("NEW ROW");

            for (int j = 0; j < 6; j++)
            {         
                if(k == 0)
                {
                    last = tmpRow[j];
                }

                if (j < 6)
                {
                    k = tmpRow[j];
                }
                else
                {
                    k = last;
                }

                //print(last + " " + k);
                // print(i + " " + j + " JA J");

                if (last == k)
                {
                    if (j < 6)
                    {
                        objsToDestroyRow.Add(tempRow[j]);

                        if(counter == 1)
                        {
                            objsToDestroyRow.Add(tempRow[j- 1]);
                        }
                    }
                    counter++;
                }
                else
                {
                    counter = 1;
                }


                if (counter == 3)
                {
                    
                    foreach(GameObject g in objsToDestroyRow)
                    {
                        rowDestruction.Add(g);
                        tmpName = g.name;
                    }

                    objsToDestroyRow.Clear();
                    row = true;
                    combo = true;
                    eleCount = 3;
                }
                else if(counter == 4)
                {
                    foreach (GameObject g in objsToDestroyRow)
                    {
                        rowDestruction.Add(g);
                        tmpName = g.name;
                    }
                    objsToDestroyRow.Clear();
                    combo = true;
                    eleCount = 4;
                }
                else if(counter == 5)
                {
                    foreach (GameObject g in objsToDestroyRow)
                    {
                        rowDestruction.Add(g);
                        tmpName = g.name;
                    }
                    objsToDestroyRow.Clear();
                    combo = true;
                    eleCount = 5;
                }
                if (counter == 1)
                {
                    objsToDestroyRow.Clear();
                }

                last = k;

            }

            if (combo)
            {
                combat.ElementalAttack(combat.CheckElement(tmpName), eleCount);
            }

            combo = false;
            //COLIMNS


            List<int> tmpColumn = columns[i];
            List<GameObject> tempColumn = columnsTrans[i];
            List<GameObject> objsToDestroyColumn = new List<GameObject>();
            objsToDestroyColumn.Clear();

            counter = 0;
            last = 0;

            k = 0;
            eleCount = 0;


            for (int j = 0; j < 6; j++)
            {
                if (k == 0)
                {
                    last = tmpColumn[j];
                }

                if (j < 6)
                {
                    k = tmpColumn[j];
                }
                else
                {
                    k = last;
                }

                if (last == k)
                {
                    if (j < 6)
                    {
                        objsToDestroyColumn.Add(tempColumn[j]);

                        if (counter == 1)
                        {
                            objsToDestroyColumn.Add(tempColumn[j - 1]);
                        }
                    }
                    counter++;
                }
                else
                {
                    counter = 1;
                }


                if (counter == 3)
                {
                    foreach (GameObject g in objsToDestroyColumn)
                    {
                        columnDestruction.Add(g);
                        tmpName = g.name;
                        combo = true;
                    }

                    objsToDestroyColumn.Clear();
                    column = true;
                    eleCount = 3;
                }
                else if (counter == 4)
                {
                    foreach (GameObject g in objsToDestroyColumn)
                    {
                        columnDestruction.Add(g);
                        tmpName = g.name;
                        combo = true;
                    }
                    objsToDestroyColumn.Clear();
                    eleCount = 4;
                }
                else if (counter == 5)
                {
                    foreach (GameObject g in objsToDestroyColumn)
                    {
                        columnDestruction.Add(g);
                        tmpName = g.name;
                        combo = true;
                    }
                    objsToDestroyColumn.Clear();
                    eleCount = 5;
                }
                if (counter == 1)
                {
                    objsToDestroyColumn.Clear();
                }

                last = k;
            }

            if (combo)
            {
                combat.ElementalAttack(combat.CheckElement(tmpName), eleCount);
            }
        }



        if (row)
        {
            if (rowDestruction.Count != 0)
            {
                foreach (Transform trans in elements)
                {
                    trans.GetComponent<Rigidbody2D>().isKinematic = false;
                }

                foreach (GameObject g in rowDestruction)
                {
                    Destroy(g);
                }

                rowDestruction.Clear();
            }
        }
        if ( column)
        { 
            if (columnDestruction.Count != 0)
            {
                foreach (Transform trans in elements)
                {
                    trans.GetComponent<Rigidbody2D>().isKinematic = false;
                }

                foreach (GameObject g in columnDestruction)
                {
                    Destroy(g);
                }

                columnDestruction.Clear();
            }
        }

        if(row || column)
        {
            StartCoroutine(WaitMazine());
        }
        else
        {
            canSwap = true;
        }
    }

    IEnumerator WaitMazine()
    {
        yield return new WaitForSeconds(0.01f);

        List<List<GameObject>> columnCount = new List<List<GameObject>>();

        for (int i = 0; i < 6; i++)
        {
            List<GameObject> emptyList = new List<GameObject>();

            columnCount.Add(emptyList);
        }

       // print("CALLED");

        foreach (Transform trans in elements)
        {
            //print(trans.GetComponent<ElementLocation>().inGridTrue);

            int column_i = trans.GetComponent<ElementLocation>().column - 1;
            //print(column_i);
            List<GameObject> gj = columnCount[column_i];

            gj.Add(trans.gameObject);
        }

        int count = 0;
        int howMany = 6;

        foreach (List<GameObject> col in columnCount)
        {
            howMany = 6;

            foreach (GameObject g in col)
            {
                howMany--;
            }

          //  print(howMany);

            StartCoroutine( eleGenerator.GenerateElements(eleGenerator.columnSpawners[count].position, howMany));

            count++;
        }

        canSwap = true;
    }
}
