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

public class Map : MonoBehaviour
{
    [Header("General")]
    private int locationPosX = 0;
    private int locationPosY = 0;

    [SerializeField] private int mapLengthMax;
    private int mapLengthCurrent;

    [Header("Map Size")]
    [Tooltip("Only positive values")] [SerializeField] private int maxMapWidth;
    [Tooltip("Only negative values")] [SerializeField] private int minMapWidth;
    [Space]
    [Tooltip("Only positive values")] [SerializeField] private int maxMapHeight;
    [Tooltip("Only negative values")] [SerializeField] private int minMapHeight;

    private int northWay;
    private int eastWay;
    private int southWay;
    private int westWay;

    [Header("Waypoints")]
    [SerializeField] private GameObject northWayObject;
    [SerializeField] private GameObject eastWayObject;
    [SerializeField] private GameObject southWayObject;
    [SerializeField] private GameObject westWayObject;
    [Space]
    [SerializeField] private GameObject northFence;
    [SerializeField] private GameObject eastFence;
    [SerializeField] private GameObject southFence;
    [SerializeField] private GameObject westFence;

    [Header("Location")]
    private Dictionary<string, LocationData> mapData = new Dictionary<string, LocationData>();
    private WaypointDirection lastWaypoint;

    [Header("LocationType")]
    private int isPeacefull;
    private int isEmpty;

    [Header("LocationGFX")]
    [SerializeField] GameObject[] buildings;

    [Header("Trader")]
    [SerializeField] private GameObject trader;
    [SerializeField] private int currentMovesToTrader;
    [SerializeField] private int maxMovesToTrader;

    [Header("Difficult")]
    [SerializeField] private int currentMovesToNextDifficultLvl;
    [SerializeField] private int maxMovesToNextDifficultLvl;

    void Start()
    {
        GenerateLocation();
        SetActiveWays();
    }

    // Генерация локации (с учетом ограничений размера карты)
    public void GenerateLocation()
    {
        // Генерируем возможные пути выхода с локации
        GenerateWays();

        isPeacefull = Random.Range(0, 3);
        SetUpLocation();

        print("Generate location is done succesfull!");
    }

    void GenerateWays()
    {
        // Генерация западного пути
        if (lastWaypoint != WaypointDirection.East)
        {
            westWay = Random.Range(0, 2);
        }
        else if (lastWaypoint == WaypointDirection.East)
        {
            westWay = 0;
        }

        // Генерация восточного пути
        if (lastWaypoint != WaypointDirection.West)
        {
            eastWay = Random.Range(0, 2);
        }
        else if (lastWaypoint == WaypointDirection.West)
        {
            eastWay = 0;
        }

        //Генерация северного пути
        if (lastWaypoint != WaypointDirection.South)
        {
            northWay = Random.Range(0, 2);
        }
        else if (lastWaypoint == WaypointDirection.South)
        {
            northWay = 0;
        }

        // Генерация южного пути
        if (lastWaypoint != WaypointDirection.North)
        {
            southWay = Random.Range(0, 2);
        }
        else if (lastWaypoint == WaypointDirection.North)
        {
            southWay = 0;
        }

        // Создание хотя-бы одного пути, если получился тупик
        if (northWay == 0 && eastWay == 0 && southWay == 0 && westWay == 0)
        {
            if (lastWaypoint == WaypointDirection.North)
            {
                northWay = 1;
            }
            else if (lastWaypoint == WaypointDirection.East)
            {
                eastWay = 1;
            }
            else if (lastWaypoint == WaypointDirection.South)
            {
                southWay = 1;
            }
            else if (lastWaypoint == WaypointDirection.West)
            {
                westWay = 1;
            }
        }
    }

    // Подготовка локации
    void SetUpLocation()
    {
        if (currentMovesToNextDifficultLvl <= 0)
        {
            Game.game.difficult += Game.game.difficultStep;
            currentMovesToNextDifficultLvl = maxMovesToNextDifficultLvl;
        }

        if(mapLengthCurrent >= mapLengthMax)
        {
            Game.game.waveManager.SpawnBoss();
            BlockWays(true);
        }
        else if (mapLengthCurrent != mapLengthMax && currentMovesToTrader <= 0 )
        {
            SetActiveTrader(true);
            currentMovesToTrader = maxMovesToTrader;
            BlockWays(false);
        }
        else
        {
            if (isPeacefull < 2)
            {
                if (isEmpty == 0)
                {
                    Game.game.waveManager.NextWave();
                    BlockWays(true);
                }
            }

            if (isPeacefull == 2)
            {
                BlockWays(false);
                //Случайная ситуация...
            }
        }
    }

    void SetActiveTrader(bool value)
    {
        trader.gameObject.SetActive(value);
    }

    // Активация действующих путей
    void SetActiveWays()
    {
        // Активация севера
        if (northWay == 1)
        {
            northWayObject.SetActive(true);
            northFence.SetActive(false);
        }
        else
        {
            northWayObject.SetActive(false);
            northFence.SetActive(true);
        }

        // Активация востока
        if (eastWay == 1)
        {
            eastWayObject.SetActive(true);
            eastFence.SetActive(false);
        }
        else
        {
            eastWayObject.SetActive(false);
            eastFence.SetActive(true);
        }

        // Активация юга
        if (southWay == 1)
        {
            southWayObject.SetActive(true);
            southFence.SetActive(false);
        }
        else
        {
            southWayObject.SetActive(false);
            southFence.SetActive(true);
        }

        // Активация запада
        if (westWay == 1)
        {
            westWayObject.SetActive(true);
            westFence.SetActive(false);
        }
        else
        {
            westWayObject.SetActive(false);
            westFence.SetActive(true);
        }
    }

    // Блокировка путей (например во время боя)
    public void BlockWays(bool value)
    {
        // Блокировка севера
        if (northWay == 1)
        {
            northWayObject.GetComponent<Waypoint>().isOpen = !value;

            if (value != false)
            {
                northWayObject.GetComponent<Waypoint>().ChangeGFX(0);
            }
            else if (value != true)
            {
                northWayObject.GetComponent<Waypoint>().ChangeGFX(1);
            }
        }

        // Блокировка востока
        if (eastWay == 1)
        {
            eastWayObject.GetComponent<Waypoint>().isOpen = !value;

            if (value != false)
            {
                eastWayObject.GetComponent<Waypoint>().ChangeGFX(0);
            }
            else if (value != true)
            {
                eastWayObject.GetComponent<Waypoint>().ChangeGFX(1);
            }
        }

        // Блокировка юга
        if (southWay == 1)
        {
            southWayObject.GetComponent<Waypoint>().isOpen = !value;

            if (value != false)
            {
                southWayObject.GetComponent<Waypoint>().ChangeGFX(0);
            }
            else if (value != true)
            {
                southWayObject.GetComponent<Waypoint>().ChangeGFX(1);
            }
        }

        // Блокировка запада
        if (westWay == 1)
        {
            westWayObject.GetComponent<Waypoint>().isOpen = !value;

            if (value != false)
            {
                westWayObject.GetComponent<Waypoint>().ChangeGFX(0);
            }
            else if (value != true)
            {
                westWayObject.GetComponent<Waypoint>().ChangeGFX(1);
            }
        }
    }

    // Сохранение локации на глобальной карте
    void SaveLocation()
    {
        string locPosX = locationPosX.ToString();
        string locPosY = locationPosY.ToString();
        string locPos = locPosX + ":" + locPosY;

        LocationData locData = new LocationData();
        locData.north = northWay;
        locData.east = eastWay;
        locData.south = southWay;
        locData.west = westWay;

        locData.isPeacefull = isPeacefull;
        locData.isEmpty = isEmpty;

        if (!mapData.ContainsKey(locPos))
        {
            mapData.Add(locPos, locData);

            print("Saved location succesfull!");
        }
    }

    // Загрузка локации
    void LoadLocation()
    {
        LocationData locData = new LocationData();
        string key = locationPosX + ":" + locationPosY;
        if (mapData.ContainsKey(key))
        {
            locData = mapData [key];

            northWay = locData.north;
            eastWay = locData.east;
            southWay = locData.south;
            westWay = locData.west;

            isPeacefull = locData.isPeacefull;
            isEmpty = locData.isEmpty;

            print("Load location succesfull!");
        }
        else
        {
            // Если не удается загрузить, значит генерируем новую локацию
            GenerateLocation();
            print("Can't load location. Trying to generate new one...");
        }
    }

    // Переход в следующую локацию
    public IEnumerator GoToNextLocation(WaypointDirection wp)
    {
        // Эффект перехода между локациями
        StartCoroutine(Game.game.ui.LocationTransitionEffect());

        lastWaypoint = wp;

        // Сохранение текущей локации
        //SaveLocation();

        yield return new WaitForSeconds(0.5f);

        // Перемещение по глобальной карте
        if (wp == WaypointDirection.North)
        {
            locationPosY += 1;
            Game.game.MovePlayerToPosition(southWayObject.transform);
        }
        else if (wp == WaypointDirection.South)
        {
            locationPosY -= 1;

            Game.game.MovePlayerToPosition(northWayObject.transform);
        }
        else if (wp == WaypointDirection.East)
        {
            locationPosX += 1;

            Game.game.MovePlayerToPosition(westWayObject.transform);
        }
        else if (wp == WaypointDirection.West)
        {
            locationPosX -= 1;

            Game.game.MovePlayerToPosition(eastWayObject.transform);
        }

        Game.game.cam.transform.position = Game.game.player.transform.position;
        SetBuildingsGFX();
        SetActiveTrader(false);

        currentMovesToTrader -= 1;
        mapLengthCurrent += 1;
        currentMovesToNextDifficultLvl -= 1;

        // Создание новой локации
        GenerateLocation();
        SetActiveWays();

        Game.game.player.GetComponent<Player>().enabled = true;

        print("Go to" + wp.ToString());
        print("Current location now: X-" + locationPosX.ToString() + ", Y-" + locationPosY.ToString());
    }

    // Изменение графики домов
    void SetBuildingsGFX()
    {
        for (int i = 0; i < buildings.Length; i++)
        {
            buildings[i].GetComponent<GraphicsSetUp>().GFXSetUp();
        }
    }

    public void SetLoadedValues(PlayerData data)
    {
        mapLengthCurrent = data.mapLengthCurrent;
        currentMovesToTrader = data.currentMovesToTrader;
        currentMovesToNextDifficultLvl = data.currentMovesToNextDifficultLvl;
    }

    public PlayerData GetSavedValues(PlayerData data)
    {
        data.mapLengthCurrent = mapLengthCurrent;
        data.currentMovesToTrader = currentMovesToTrader;
        data.currentMovesToNextDifficultLvl = currentMovesToNextDifficultLvl;

        return data;
    }
}
