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

public class GridSystemVisual : MonoBehaviour
{
    public static GridSystemVisual Instance {get; private set;}
    [Serializable]
    public struct GridVisaulTypeMaterial {
        public GridVisualType gridVisualType;
        public Material material;
    }
    public enum GridVisualType {
        White
        ,Blue
        ,Red
        ,RedSoft
        ,Yellow
    }
    [SerializeField] private Transform gridSystemVisualSinglePrefab;
    [SerializeField] private List<GridVisaulTypeMaterial> gridVisualTypeMaterialList;
    private GridPosition hoverGridPosition = new GridPosition(-1,-1);
    private GridSystemVisualSingle[,] gridSystemVisualSingleArray;
     private void Awake() 
    {
        if (Instance != null)
        {
            Debug.LogError("There's more than one GridSystemVisual" + transform + " - " + Instance);
            Destroy(gameObject);
            return;
        }
        Instance = this;
    }
    private void Start() {
        LevelGrid levelGrid = LevelGrid.Instance;

        gridSystemVisualSingleArray = new GridSystemVisualSingle[
            levelGrid.GetWidth(),
            levelGrid.GetHeight()
        ];

        for (int x = 0; x < levelGrid.GetWidth(); ++x) {
            for (int z = 0; z < levelGrid.GetHeight(); ++z) {
                GridPosition gridPosition = new GridPosition(x,z);
                Transform gridSystemVisualSingleTransform = 
                    Instantiate(gridSystemVisualSinglePrefab, levelGrid.GetWorldPosition(gridPosition), Quaternion.identity);
                
                gridSystemVisualSingleArray[x, z] = gridSystemVisualSingleTransform.GetComponent<GridSystemVisualSingle>();
            }
        }

        UnitActionSystem.Instance.OnSelectedActionChanged += UnitActionSystem_OnSelectedActionChanged;
        LevelGrid.Instance.OnAnyUnitMovedGridPosition += LevelGrid_OnAnyUnitMovedGridPosition;
        HideAllGridPosition();
        UpdateGridVisual();
    }

    private void UnitActionSystem_OnSelectedActionChanged(object sender, EventArgs empty) {
        UpdateGridVisual();
    }
    private void LevelGrid_OnAnyUnitMovedGridPosition(object sender, EventArgs empty) {
        UpdateGridVisual();
    }
    private void Update() {

        GridPosition newHoverGridPosition = LevelGrid.Instance.GetGridPosition(MouseWorld.GetPosition());
        if (!LevelGrid.Instance.IsValidGridPosition(newHoverGridPosition)) {
            return;
        }
        if (hoverGridPosition == newHoverGridPosition) {
            return;
        }
        hoverGridPosition = newHoverGridPosition;
        UpdateGridVisual();
    }
    private void UpdateGridVisual() {
        HideAllGridPosition();
        BaseAction selectedAction = UnitActionSystem.Instance.GetSelectedAction();
        GridVisualType gridVisualType;
        switch (selectedAction) {
            default:
            case MoveAction action:
                gridVisualType = GridVisualType.White;
                ShowGridPositionList(UnitActionSystem.Instance.GetSelectedAction().GetValidActionGridPosition(),gridVisualType);
                break;
            case SpinAction action:
                gridVisualType = GridVisualType.Blue;
                ShowGridPositionList(UnitActionSystem.Instance.GetSelectedAction().GetValidActionGridPosition(),gridVisualType);
                break;
            case ShootAction action:
                ShowGridPositionList(selectedAction.GetValidActionRangeGridPosition(), GridVisualType.RedSoft);

                gridVisualType = GridVisualType.Red;
                ShowGridPositionList(UnitActionSystem.Instance.GetSelectedAction().GetValidActionGridPosition(),gridVisualType);
                break;
            case SwordAction action:
                ShowGridPositionList(selectedAction.GetValidActionRangeGridPosition(), GridVisualType.RedSoft);

                gridVisualType = GridVisualType.Red;
                ShowGridPositionList(UnitActionSystem.Instance.GetSelectedAction().GetValidActionGridPosition(),gridVisualType);
                break;
            case GrenadeAction action:
                gridVisualType = GridVisualType.Yellow;
                ShowGridPositionList(UnitActionSystem.Instance.GetSelectedAction().GetValidActionGridPosition(),gridVisualType);

                if (UnitActionSystem.Instance.GetSelectedAction().IsValidActionGridPosition(hoverGridPosition)) {
                    ShowGridPositionList(GrenadeProjectile.GetDamageableInBlastRange(LevelGrid.Instance.GetWorldPosition(hoverGridPosition))
                                                          .Select(target => target.GetGridPosition()),
                                         GridVisualType.Red);
                }
                break;
            case InteractAction action:
                gridVisualType = GridVisualType.Blue;
                ShowGridPositionList(UnitActionSystem.Instance.GetSelectedAction().GetValidActionGridPosition(),gridVisualType);
                break;
        }
    }
    public void HideAllGridPosition() {
        foreach (GridSystemVisualSingle gridSystemVisualSingle in gridSystemVisualSingleArray) {
                gridSystemVisualSingle.Hide();
        }
    }

    public void ShowGridPositionList(IEnumerable<GridPosition> gridPositionsList, GridVisualType gridVisualType) {
        foreach (GridPosition gridPosition in gridPositionsList) {
            gridSystemVisualSingleArray[gridPosition.x, gridPosition.z].Show(GetGridVisualTypeMaterial(gridVisualType));
        }
    }

    private Material GetGridVisualTypeMaterial(GridVisualType gridVisualType) =>
        gridVisualTypeMaterialList.Find(gridVisaulTypeMaterial => 
            gridVisaulTypeMaterial.gridVisualType == gridVisualType
        ).material;
}