using map;
using System;
using System.Text.RegularExpressions;
using UnityEngine;

public class PixelMapState : State {
    [SerializeField] private Transform rootTransform = null; // Set from editor
    [SerializeField] private Sprite[] starsSprites = new Sprite[4]; // Set from editor
    [SerializeField] private Transform heroStarShip = null; // Set from editor
    [SerializeField] private Transform selector = null; // Set from editor
    [SerializeField] private PixelFontMesh statusText = null; // Set from editor
    [SerializeField] private PixelFontMesh coordText = null; // Set from editor
    // TODO remove serialized
    [SerializeField] private Coord selectorPosition = new Coord(1, 1); // Serialize for debug

    private Coord fieldSize = new Coord(10, 9);

    const int spriteSize = 8;
    StarMap map;

    protected override void Init() {
        map = StarMap.LoadFromResources();
        GenerateMap(map);
        PlayerData.LoadPlayer(map);
        OnStateShow();
    }

    protected override void OnStateShow() {
        selectorPosition = PlayerData.Instance.Position;
        SetPosition(selectorPosition);
        MoveSelector(new Coord());
        PlayerData.Instance.Save();
    }

    private void SetPosition(Coord position) {
        rootTransform.localPosition = new Vector3(4, 4) - GetSpritePosition(position);
        heroStarShip.localPosition = GetSpritePosition(position);
    }

    private void GenerateMap(StarMap map) {
        foreach (var point in map.points) {
            if (point != null) {
                GenerateSprite(point.position, GetSpriteByName(point.spriteId));
            }
        }
    }

    private Sprite GetSpriteByName(string spriteId) {
        foreach (var sprite in starsSprites) {
            if (sprite != null && sprite.name == spriteId) {
                return sprite;
            }
        }
        return null;
    }

    private void GenerateSprite(Coord position, Sprite sprite) {
        string name = "object";
        if (sprite != null) {
            name = sprite.name;
        }
        SpriteRenderer spriteRenderer = Utils.Create<SpriteRenderer>(rootTransform, GetSpritePosition(position), name);
        spriteRenderer.sprite = sprite;
    }

    public static Vector3 GetSpritePosition(Coord coord) {
        return new Vector3(coord.x, coord.y) * spriteSize + new Vector3(128, 128);
    }

    void Update () {
        if (!PlayerData.Instance.StartQuestShowed) {
            PlayerData.Instance.StartQuestShowed = true;
            PlayerData.Instance.StartQuest(map.startQuestId);
        }
        if (GetKeyDown(KeyCode.F10)) {
            ResetGame();
        }
        if (GetKeyDown(KeyCode.W)) {
            MoveSelector(new Coord(0, 1));
        }
        if (GetKeyDown(KeyCode.S)) {
            MoveSelector(new Coord(0, -1));
        }
        if (GetKeyDown(KeyCode.A)) {
            MoveSelector(new Coord(-1, 0));
        }
        if (GetKeyDown(KeyCode.D)) {
            MoveSelector(new Coord(1, 0));
        }
        if (GetKeyDown(KeyCode.UpArrow)) {
            MoveSelector(new Coord(0, 1));
        }
        if (GetKeyDown(KeyCode.DownArrow)) {
            MoveSelector(new Coord(0, -1));
        }
        if (GetKeyDown(KeyCode.LeftArrow)) {
            MoveSelector(new Coord(-1, 0));
        }
        if (GetKeyDown(KeyCode.RightArrow)) {
            MoveSelector(new Coord(1, 0));
        }
        if (GetKeyDown(KeyCode.Space)) {
            SelectCurrent();
        }
        if (GetKeyDown(KeyCode.Z)) {
            SelectCurrent();
        }
        if (GetKeyDown(KeyCode.X)) {
            SelectCurrent();
        }
        if (prevKeyHitTimer >= 0) {
            prevKeyHitTimer -= Time.deltaTime;
        }
        if (GetKeyDown(KeyCode.Escape)) {
            Application.Quit();
        }
    }

    private const float keyHitDelay = 0.12f;
    private float prevKeyHitTimer = 0;
    private bool GetKeyDown(KeyCode key) {
        if (Input.GetKeyDown(key)) {
            prevKeyHitTimer = keyHitDelay;
            return true;
        }
        if (prevKeyHitTimer <= 0) {
            if (Input.GetKey(key)) {
                prevKeyHitTimer = keyHitDelay;
                return true;
            }
        }
        return false;
    }

    public void ResetGame() {
        PlayerData.CreateNewPlayer(map);
        OnStateShow();
        Debug.Log("Reset player");
    }

    private void SelectCurrent() {
        if (selectorPosition == PlayerData.Instance.Position) {
            // already here
            foreach (var point in map.points) {
                if (selectorPosition == point.position) {
                    // Set dialog
                    PlayerData.Instance.Container.SetItems(map.defaultPlanetParams);
                    PlayerData.Instance.Container.SetItems(point.startParams);
                    PlayerData.Instance.SetTexts(point.textVariables);
                    PlayerData.Instance.StartQuest(point.questId);
                    PlayerData.Instance.Save();
                    return;
                }
            }
            return;
        }
        if (selectorPosition == PlayerData.Instance.Position + new Coord(-1, 1)) {
            // your ship
            PlayerData.Instance.StartQuest(map.shipQuestId);
            PlayerData.Instance.Save();
            return;
        }
        foreach (var point in map.points) {
            if (selectorPosition == point.position && !string.IsNullOrEmpty(point.questId)) {
                // Set dialog
                PlayerData.Instance.Container.SetItems(map.defaultPlanetParams);
                PlayerData.Instance.Container.SetItems(point.startParams);
                PlayerData.Instance.SetTexts(point.textVariables);
                PlayerData.Instance.FlyToQuest(point);
                PlayerData.Instance.Save();
                return;
            }
        }
        // empty
    }

    private void MoveSelector(Coord coord) {
        selectorPosition += coord;
        if (selectorPosition.x < PlayerData.Instance.Position.x - fieldSize.x) {
            selectorPosition.x = PlayerData.Instance.Position.x - fieldSize.x;
        }
        if (selectorPosition.y < PlayerData.Instance.Position.y - fieldSize.y + 1) {
            selectorPosition.y = PlayerData.Instance.Position.y - fieldSize.y + 1;
        }
        if (selectorPosition.x >= PlayerData.Instance.Position.x + fieldSize.x) {
            selectorPosition.x = PlayerData.Instance.Position.x + fieldSize.x - 1;
        }
        if (selectorPosition.y >= PlayerData.Instance.Position.y + fieldSize.y) {
            selectorPosition.y = PlayerData.Instance.Position.y + fieldSize.y - 1;
        }
        selector.transform.localPosition = GetSpritePosition(selectorPosition);
        SetStatusText();
    }

    private void SetStatusText() {
        coordText.SetText(string.Format("{0:D2}:{1:D2}", selectorPosition.x, selectorPosition.y));
        if (selectorPosition == PlayerData.Instance.Position + new Coord(-1, 1)) {
            SetText("Твой корабль");
            return;
        }
        foreach (var point in map.points) {
            if (selectorPosition == point.position) {
                SetText(point.description);
                return;
            }
        }
        SetText(String.Empty);
    }

    private void SetText(string text) {
        if (statusText != null) {
            statusText.Text = text;
        }
    }
}
