using System;
using System.Collections;
using TMPro;
using UnityEngine;
using System.Collections.Generic;
using Unity.VisualScripting;


public abstract class Room : MonoBehaviour
{
    [SerializeField] private List<GameObject> adjacentRooms;
    [SerializeField] private bool isEntrance;
    [SerializeField] protected RoomReward roomReward;
    public event EventHandler<Room> RoomExploredByDice;
    public static event Action<Room> RoomExploredByTorch;
    private Color _roomNumberOriginalColor;
    private DicePair _diceSelected;
    
    protected bool _isExplored = false;
    protected Lock[] _locks;
    private bool _usingTorchAbility = false;
    
    private void OnEnable() {
        GameManager.StateChanged += HandleStateChange;
        GameManager.DiceSelected += HandleDiceSelected;
        GameManager.DiceUnselected += HandDiceUnselected;
        TorchAbility.TorchAbilityUsed += HandleTorchAbilityUsed;
        RoomExploredByTorch += HandleRoomExploredByTorch;
    }

    private void OnDisable() {
        GameManager.StateChanged -= HandleStateChange;
        GameManager.DiceSelected -= HandleDiceSelected;
        GameManager.DiceUnselected -= HandDiceUnselected;
        TorchAbility.TorchAbilityUsed -= HandleTorchAbilityUsed;
    }

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start() {
        InitializeRoom();
        _roomNumberOriginalColor = gameObject.GetComponentInChildren<TextMeshProUGUI>().color;
    }

    public bool GetRoomExplored()
    {
        return _isExplored;
    }

    public abstract void SetRoomExplored();

    protected virtual void InitializeRoom() {
        if (isEntrance) {
            SetPropertiesOfEntrance();
        }
        _locks = gameObject.GetComponents<Lock>();
    }

    protected void HighlightRoomAsOption()
    {
        gameObject.GetComponentInChildren<TextMeshProUGUI>().color = Color.blue;
    }

    protected void UnhighlightRoomAsOption()
    {
        gameObject.GetComponentInChildren<TextMeshProUGUI>().color = _roomNumberOriginalColor;
    }

    void SetPropertiesOfEntrance() {
        gameObject.GetComponent<SpriteRenderer>().color = Color.green;
        isEntrance = true;
    }
    
    void OnMouseDown() {
        if (!CheckIfValidRoomToExplore()) return;

        switch (GameManager.State)
        {
            case GameState.PickRoomOne:
            case GameState.PickRoomTwo:
                if (TryUnlock(_diceSelected))
                {
                    OnRoomExploredByDice();
                    SetRoomExplored();
                }
                else if(_usingTorchAbility && CheckIfValidRoomToExplore())
                {
                    SetRoomExplored();
                    OnRoomExploredByTorch();
                }
                break;
            default:
                if (_usingTorchAbility && CheckIfValidRoomToExplore())
                {
                    SetRoomExplored();
                    OnRoomExploredByTorch();
                }
                break;
        }
    }

    protected virtual void OnRoomExploredByDice() {
        RoomExploredByDice?.Invoke(this, this);
    }

    private void OnRoomExploredByTorch()
    {
        RoomExploredByTorch?.Invoke(this);
    }

    // Check if the room is valid to be explored. If so trigger the event.
    private bool CheckIfValidRoomToExplore() {
        if (_isExplored) {
            return false;
        }
        
        if (isEntrance) {
            // All entrance rooms are valid to be explored.
            return true;
        }
        else if (HasExploredAdjacentRooms()) {
            // Otherwise the room must have an adjacent room explored.
            return true;
        }
        return false;
    }

    bool HasExploredAdjacentRooms() {
        foreach (GameObject adjacentRoom in adjacentRooms) {
            if (adjacentRoom.GetComponent<Room>()._isExplored)
            {
                return true;
            }
        }
        return false;
    }

    public abstract bool TryUnlock(DicePair pair);

    private void HandleStateChange(GameState state) {
        UnhighlightRoomAsOption();
        switch (state)
        {
            case GameState.PickDiceOne:
            case GameState.PickDiceTwo:
                _diceSelected = null;
                break;
        }
    }

    private void HandleDiceSelected(DicePair pair)
    {
        _diceSelected = pair;
        if (TryUnlock(pair) && CheckIfValidRoomToExplore())
        {
            HighlightRoomAsOption();
        }
    }

    private void HandDiceUnselected()
    {
        _diceSelected = null;
        UnhighlightRoomAsOption();
    }

    private void HandleTorchAbilityUsed()
    {
        if (CheckIfValidRoomToExplore())
        {
            _usingTorchAbility = true;
            HighlightRoomAsOption();
        }
    }

    private void HandleRoomExploredByTorch(Room roomExploredByTorch)
    {
        _usingTorchAbility = false;
        if (_diceSelected != null && TryUnlock(_diceSelected))
        {
            return;
        }
        UnhighlightRoomAsOption();
    }
}
