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

public class BoardManager : MonoBehaviour
{
    public static bool CheckCollision(Vector2Int pos)
    {
        return Instance.CheckCollision(pos.x, pos.y);
    }
    public static bool Interact(Vector2Int pos, Equipment item)
    {
        bool returnVal = false;
        switch (item)
        {
            case Equipment.NONE:
                returnVal = Instance.m_Board.Reveal(pos);
                break;
            case Equipment.Candle:
                returnVal = Instance.m_Board.Mark(pos);
                break;
            case Equipment.Gravestone:
                returnVal = Instance.m_Board.Grave(pos);
                break;
        }
        return returnVal;
    }
    public static BoardEntity Talk(Vector2Int pos)
    {
        foreach(BoardEntity b in Instance.m_Entities)
        {
            if(pos == b.BoardPosition && b.m_Talkable)
            {
                return b;
            }
        }
        return null;
    }
    public BoardEntity m_Ghost;
    public BoardEntity m_BadGhost;
    public Gravestone m_Gravestone;
    public static BoardManager Instance = null;
    public int size = 256;
    public SpriteRenderer[,] boardSprites;
    public Sprite testSprite;
    public GameObject prefab;
    [SerializeField] private AudioClip sfx_Break, sfx_Ghost, sfx_Item;

    private Color[] pixels;
    public Texture2D map;

    private Board m_Board;

    private List<BoardEntity> m_Entities;// = new List<BoardEntity>();
    Player m_Player;
    private BoardChunk m_ChunkRenderer = null;
    private NumberRenderer m_NumberRenderer = null;
    private void Awake()
    {
        Instance = this;
        m_ChunkRenderer = transform.GetChild(0).GetComponent<BoardChunk>();
        m_NumberRenderer = transform.GetChild(1).GetComponent<NumberRenderer>();
    }

    // Start is called before the first frame update
    void Start()
    {
        m_Board = new Board();
        m_Board.BuildBoard(size);
        m_Board.CellChanged += OnCellChanged;

        m_Entities = new List<BoardEntity>(FindObjectsOfType<BoardEntity>());
        m_Player = GameObject.FindGameObjectWithTag("Player").GetComponent<Player>();
        m_Player.DeathAction += OnPlayerDeath;
        ResetStage();

        for(int i = 508; i < 517; i++)
        {
            for (int j = 508; j < 517; j++)
            {
                m_Board.ClearCell(new Vector2Int(i, j));
            }
        }

        pixels = new Color[size * size];

        for (int y = 0; y < size; y++)
        {
            for (int x = 0; x < size; x++)
            {
                m_Board.GetCell(x, y);
                
                if (m_Board.GetCell(x, y).m_EntityID > 0)
                {
                    pixels[x + y * size] = Color.red;
                }
                else
                {
                    if (m_Board.GetCell(x, y).Hidden)
                    {
                        pixels[x + y * size] = Color.grey;
                    }
                    else
                    {
                        pixels[x + y * size] = Color.white;
                    }
                }
            }
        }
        map.SetPixels(pixels);
        map.Apply();

        m_ChunkRenderer.RebuildChunk(m_Board.GetBoard, new Vector2Int(512,512));
    }

    private void Update()
    {
        for(int i=0; i < m_Entities.Count;)
        {
            if (!m_Entities[i].BoardUpdate())
            {
                i++;
            }
            else
            {
                Destroy(m_Entities[i].gameObject);
                m_Entities.RemoveAt(i);
            }
        }
    }

    public bool CheckCollision(int x, int y)
    {
        return !m_Board.GetCell(x, y).Hidden && CheckEntityCollision(x,y);
    }

    public bool CheckEntityCollision(int x, int y)
    {
        Vector2Int p = new Vector2Int(x, y);
        foreach (BoardEntity b in Instance.m_Entities)
        {
            if (p == b.BoardPosition )
            {
                return false;
            }
        }
        return true;
    }

    private void OnCellChanged(Vector2Int pos, Cell cell)
    {
        m_ChunkRenderer.UpdateCell(cell, pos);

        switch (cell.State)
        {
            case CellState.Hidden:
                break;
            case CellState.Graved:
                {
                    Gravestone g = Instantiate<Gravestone>(m_Gravestone);
                    g.SetUp(cell);
                    g.BoardPosition = pos;
                    m_Entities.Add(g);
                }
                break;
            case CellState.Marked:
                break;
            case CellState.Revealed:
                switch (cell.m_EntityType)
                {
                    case EntityType.None:
                        SoundManager.PlayOneShot(sfx_Break);
                        break;
                    case EntityType.Ghost:
                        if (cell.m_EntityID == 1)
                        {
                            BoardEntity g = Instantiate<BoardEntity>(m_BadGhost);
                            g.BoardPosition = pos;
                            m_Entities.Add(g);
                        }
                        SoundManager.PlayOneShot(sfx_Ghost);
                        break;
                    case EntityType.Item:
                        SoundManager.PlayOneShot(sfx_Item);
                        break;
                }
                break;
        }

        if (cell.Hidden)
        {
            map.SetPixel(pos.x, pos.y, Color.grey);
        }
        else
        {
            
            
            map.SetPixel(pos.x, pos.y, Color.white);
        }
        map.Apply();
    }

    public void SpawnNumbers(Vector2Int pos)
    {
        List<Vector2Int> positions = new List<Vector2Int>();
        for (int y = pos.y - 1; y < pos.y + 2; y++) { 
            for (int x = pos.x - 1; x < pos.x + 2; x++)
            {
                if(!m_Board.GetCell(x,y).Hidden)
                    positions.Add(new Vector2Int(x, y));
            }
        }

        List<Vector2Int> finalPositions = new List<Vector2Int>();
        List<int> counts = new List<int>();
        int c = 0;
        for(int i=0; i < positions.Count; i++)
        {
            c = m_Board.CheckSurroundingEntities(positions[i]);
            if (c > 0)
            {
                counts.Add(c);
                finalPositions.Add(positions[i]);
            }
            
        }
        m_NumberRenderer.RefreshNumbers(counts.ToArray(), finalPositions.ToArray());
    }

    private void OnPlayerDeath()
    {
        ScreenWipe.Instance.BeginWipe(true, MidWipe);
    }

    private void MidWipe()
    {
        ResetStage();
        ScreenWipe.Instance.BeginWipe(false, null);
    }

    private void ResetStage()
    {
        for(int i=0; i < m_Entities.Count;)
        {
            if (m_Entities[i] is BadGhost)
            {
                Destroy(m_Entities[i].gameObject);
                m_Entities.RemoveAt(i);
            }
            else if (m_Entities[i] is DialogueEntity d)
            {
                i++;
                d.UpdateDialogue();
            }
            else
            {
                i++;
            }
        }
        m_Player.Spawn(new Vector2Int(512, 512));
    }
}
