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

public class InfluenceRadius : MonoBehaviour
{
    [SerializeField] private Vector3 initScale = new Vector3(8, 8, 8);
    //[SerializeField] private GameObject frameMarker;

    public int ID { get; private set; }

    public bool Dragging { get; private set; }
    //private Vector3 tempMousePos;
    //private Vector3 enlargeScale = new Vector3(2, 2, 2);
    private List<GameObject> collidedHouses;
    private List<GameObject> newCols;
    private int radius;
    //private List<GameObject> frames;

    void OnEnable()
    {
        Dragging = true;
        collidedHouses = new List<GameObject>();
        transform.localScale = initScale;
        radius = Mathf.FloorToInt( transform.localScale.x / 2);

        // Create ObjectPool
        /*frames = new List<GameObject>();
        for (int i = 0; i < 29; i++)
        {
            GameObject frame = Instantiate(frameMarker, this.transform);
            float newScaleX = frame.transform.localScale.x / this.transform.localScale.x;
            float newScaleY = frame.transform.localScale.y / this.transform.localScale.y;
            float newScaleZ = frame.transform.localScale.z / this.transform.localScale.z;
            frame.transform.localScale = new Vector3(newScaleX, newScaleY, newScaleZ);
            frame.SetActive(false);
            frames.Add(frame);
        }*/
    }

    public void MouseUp(int id)
    {
        Dragging = false;
        ID = id;
        GameManager.Instance.InfluenceAdded(this);
        ConnectHouses();
    }

    private void ConnectHouses()
    {
        for (int i = 0; i < collidedHouses.Count; i++)
        {
            collidedHouses[i].GetComponent<HouseController>().SetConnected();
        }
    }

    void Update()
    {
        if(Dragging)
        {
            //transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition);// - Camera.main.transform.position;
            //tempMousePos = transform.position;
            //tempMousePos.z = 0;
            //transform.position = tempMousePos;
            if (Snap(Camera.main.ScreenToWorldPoint(Input.mousePosition)))
            {
                Collider2D[] cols = Physics2D.OverlapCircleAll(transform.position, radius, GameManager.Instance.HousesLayerMask);
                newCols = new List<GameObject>();
                for (int i = 0; i < cols.Length; i++)
                {
                    newCols.Add(cols[i].gameObject);
                }

                CheckCollided(newCols);

                /*List<Vector3Int> insidePoints = GetInfluencedLocations();

                List<Vector3> castedLocations = new List<Vector3>();
                for (int i = 0; i < insidePoints.Count; i++)
                {
                    castedLocations.Add(insidePoints[i]);
                }

                DeactiveOutsideGameObjects(castedLocations);

                for (int i = 0; i < insidePoints.Count; i++)
                {
                    GameObject frameToShow = GetNextInactiveObject();
                    frameToShow.transform.position = insidePoints[i];
                    frameToShow.SetActive(true);
                }*/
            }
            /*string[] colNames = new string[cols.Length];
            print("Overlapped: " + cols.Length);
            for (int i = 0; i < cols.Length; i++)
            {
                colNames[i] = cols[i].name;
            }
            print("Names: " + string.Join(", ", colNames));*/
        }

        if (Input.GetKeyDown(KeyCode.Space))
            print("----------------------------------------------------------");
        if (Input.GetKeyDown(KeyCode.C))
            PrintList("Locations",GetInfluencedLocations());
    }

    private bool Snap(Vector3 worldMousePos)
    {
        int x = Mathf.RoundToInt(worldMousePos.x);
        int y = Mathf.RoundToInt(worldMousePos.y);

        if (x == transform.position.x && y == transform.position.y)
            return false;

        transform.position = new Vector3(x, y, 0);
        return true;
    }

    /*public void EnlargeScale()
    {
        this.transform.localScale += enlargeScale;
        radius = Mathf.FloorToInt(transform.localScale.x / 2);
    }*/

    private void CheckCollided(List<GameObject> newColArray)
    {
        List<GameObject> listCopy = new List<GameObject>(newColArray);
        List<GameObject> commonCols = new List<GameObject>();

        //PrintList("New col 1", newColArray);
        //PrintList("CurrentHouses 1", collidedHouses);

        for (int i = 0; i < newColArray.Count; i++)
        {
            if (collidedHouses.Contains(newColArray[i]))
            {
                commonCols.Add(newColArray[i]);
                listCopy.Remove(newColArray[i]);
                collidedHouses.Remove(newColArray[i]);
            }
        }

        // What remains in the collided houses is the old houses
        for (int i = 0; i < collidedHouses.Count; i++)
        {
            HouseController hc = collidedHouses[i].GetComponent<HouseController>();
            if (hc != null)
            {
                //hc.ClearHouse();
                hc.HouseOutOfRegion();
            }
        }

        // What remains in the listCopy are the new houes
        for (int i = 0; i < listCopy.Count; i++)
        {
            HouseController hc = listCopy[i].GetComponent<HouseController>();
            if (hc != null)
            {
                //hc.PaintHouse();
                hc.HouseInTempRegion();
            }
        }

        collidedHouses = new List<GameObject>();
        collidedHouses.AddRange(commonCols);
        collidedHouses.AddRange(listCopy);

        //PrintList("CurrentHouses 2", collidedHouses);
    }

    /*private GameObject GetNextInactiveObject()
    {
        for (int i = 0; i < frames.Count; i++)
        {
            if (!frames[i].activeInHierarchy)
                return frames[i];
        }

        GameObject frame = Instantiate(frameMarker, this.transform);
        float newScaleX = frame.transform.localScale.x / this.transform.localScale.x;
        float newScaleY = frame.transform.localScale.y / this.transform.localScale.y;
        float newScaleZ = frame.transform.localScale.z / this.transform.localScale.z;
        frame.transform.localScale = new Vector3(newScaleX, newScaleY, newScaleZ);
        frame.SetActive(false);
        frames.Add(frame);
        return frame;
    }

    private void DeactiveOutsideGameObjects(List<Vector3> locations)
    {
        for (int i = 0; i < frames.Count; i++)
        {
            if(!locations.Contains(frames[i].transform.position))
            {
                frames[i].SetActive(false);
            }
        }
    }*/

    public List<Vector3Int> GetInfluencedLocations()
    {
        List<Vector3Int> result = new List<Vector3Int>();
        //print("Pos: " + transform.position + "; " + radius);

        int minY = Mathf.FloorToInt(transform.position.y - radius);
        int maxY = Mathf.FloorToInt(transform.position.y + radius);
        int minX = Mathf.FloorToInt(transform.position.x - radius);
        int maxX = Mathf.FloorToInt(transform.position.x + radius);

        for (int i = minY; i <= maxY; i++)
        {
            for (int j = minX; j < maxX; j++)
            {
                int yPoint = Mathf.FloorToInt(i - transform.position.y);
                int xPoint = Mathf.FloorToInt(j - transform.position.x);

                if (((xPoint * xPoint) + (yPoint * yPoint)) <= radius * radius)
                {
                    Vector3Int a = new Vector3Int(j, i, 0);
                    result.Add(a);
                }
            }
        }

        return result;
    }

    private void PrintList<T>(string listName, List<T> gos)
    {
        if (gos == null || gos.Count == 0)
            return;

        string result = "List " + listName + ":\n";
        for (int i = 0; i < gos.Count; i++)
        {
            if(typeof(T) == typeof(GameObject))
                result += (gos[i] as GameObject).name + ", ";
            else
                result += gos[i].ToString() + ", ";
        }
        print(result);
    }
}
