using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class DialogSystem : MonoBehaviour {

    private void Awake() {
        choicePanel.GetComponent<CanvasGroup>().alpha = 0;
        choicePanel.GetComponent<CanvasGroup>().blocksRaycasts = false;
        choicePanel.GetComponent<CanvasGroup>().interactable = false;
    }
    public NameAndDialogController nameAndDialogController;
    public CharacterGenerator characterGenerator;

    Queue<string> mainEvents = new Queue<string>();
    bool doNext = true;
    string labelJump = "";

    int[] flags = new int[] { 0 };

    void Update() {
        if (mainEvents.Count > 0 && doNext) {
            StartCoroutine(DoEvent(mainEvents.Dequeue()));
        }
        else if (mainEvents.Count == 0 && doNext) {
            GameManager.instance.day.NewDay();
        }
    }

    public void QueueDialog(List<string> scriptLines) {
        foreach (var line in scriptLines) {
            mainEvents.Enqueue(line.Trim());
        }
    }

    IEnumerator DoEvent(string eventString) {
        doNext = false;
        bool skipEvent = false;
        string[] lineContents = eventString.Split('|');

        //label checking
        if (lineContents == null || lineContents.Length <= 0 || string.IsNullOrWhiteSpace(lineContents[0])) {
            skipEvent = true;
        }

        if (!skipEvent) {
            if (!string.IsNullOrWhiteSpace(labelJump)) {
                if (lineContents[0].ToLower().Equals("label")) {
                    if (lineContents[1].ToLower().Equals(labelJump.ToLower())) {
                        labelJump = "";
                    }
                    else {
                        skipEvent = true;
                    }
                }
                else {
                    skipEvent = true;
                }
            }
        }

        if (!skipEvent) {

            switch (Enum.Parse(typeof(GameEventType), lineContents[0], true)) {
                case GameEventType.SAY:
                    yield return StartCoroutine(ShowDialog(lineContents[1], lineContents[2]));
                    break;
                case GameEventType.SHOW_CHARACTER:
                    if (lineContents[1].ToLower().Equals("male_customer")) {
                        characterGenerator.GenerateRandomMaleCharacter();
                    }
                    else if (lineContents[1].ToLower().Equals("female_customer")) {
                        characterGenerator.GenerateRandomFemaleCharacter();
                    }
                    else if (lineContents[1].ToLower().Equals("mixed_customer")) {
                        characterGenerator.GenerateRandomMixedCharacter();
                    }
                    else if (lineContents[1].ToLower().Equals("none")) {
                        characterGenerator.HideCharacter();
                    }
                    else {
                        characterGenerator.GenerateNamedCharacter(lineContents[1].ToLower());
                    }
                    break;
                case GameEventType.SHOW_BACKGROUND:
                    Debug.Log("backgronas  dfasdtg  hasdg");
                    break;
                case GameEventType.CHOICE:
                    Debug.Log("Executing choice");
                    int halfLength = (lineContents.Length - 1) / 2;
                    yield return StartCoroutine(ShowChoice(lineContents.ToList().GetRange(1, halfLength), lineContents.ToList().GetRange(1 + halfLength, halfLength)));
                    break;
                case GameEventType.JUMP:
                    labelJump = lineContents[1];
                    break;
                case GameEventType.GIVE:
                    GameManager.instance.inventory.Add(lineContents[1].ToLower());
                    break;
                case GameEventType.REMOVE:
                    GameManager.instance.inventory.Remove(lineContents[1].ToLower());
                    break;
                case GameEventType.USEPOINT:
                    int delta = 0;
                    int.TryParse(lineContents[1], out delta);
                    GameManager.instance.day.ChangeActionPoints(delta);
                    break;
                case GameEventType.DEVIANCE:
                    GameManager.instance.devianceController.deviance += int.Parse(lineContents[1]);
                    break;
                case GameEventType.HIDE:
                    GameManager.instance.HideGameObjectActive(lineContents[1]);
                    break;
                case GameEventType.SHOW:
                    GameManager.instance.ShowGameObjectActive(lineContents[1]);
                    break;
                case GameEventType.GAMEOVER:
                    yield return StartCoroutine(DoGameOver());
                    break;
                case GameEventType.END:
                    SceneManager.LoadScene("MainMenu");
                    break;
                default:
                    break;
            }
        }
        doNext = true;
    }

    public CanvasGroup gameOver;
    IEnumerator DoGameOver() {
        gameOver.alpha = 1;
        gameOver.blocksRaycasts = true;
        gameOver.interactable = true;

        yield return StartCoroutine(WaitForKeyDown(new List<KeyCode>() { KeyCode.Space, KeyCode.Return, KeyCode.RightArrow, KeyCode.DownArrow, KeyCode.Mouse0 }));
#if UNITY_EDITOR
        UnityEditor.EditorApplication.isPlaying = false;
#else
        Application.Quit();
#endif
    }

    IEnumerator ShowDialog(string name, string line) {
        int startReplaceIdx = -1;
        int endReplaceIdx = -1;
        for (int i = 0; i < line.Length; i++) {
            if (line[i] == '{') {
                startReplaceIdx = i;
                endReplaceIdx = -1;
            }
            if (line[i] == '}') {
                endReplaceIdx = i;
            }

            if (startReplaceIdx != -1 && endReplaceIdx != -1) {
                string keyWord = line.Substring(startReplaceIdx + 1, endReplaceIdx - startReplaceIdx - 1);

                StreamReader stream = new StreamReader(Application.dataPath + "/Resources/Dialog/WordBanks/" + keyWord + ".txt");
                string contents = stream.ReadToEnd();
                stream.Close();
                string[] replacements = contents.Split('\n');
                int randIdx = new System.Random().Next(replacements.Length);
                string replacement = replacements[randIdx].Trim();

                line = line.Substring(0, startReplaceIdx) + replacement + line.Substring(endReplaceIdx + 1, line.Length - endReplaceIdx - 1);
                startReplaceIdx = -1;
                endReplaceIdx = -1;
            }
        }
        nameAndDialogController.setMainDialogText(line);
        nameAndDialogController.setNamePlateText(name);

        yield return StartCoroutine(WaitForKeyDown(new List<KeyCode>() { KeyCode.Space, KeyCode.Return, KeyCode.RightArrow, KeyCode.DownArrow, KeyCode.Mouse0 }));
    }

    IEnumerator WaitForKeyDown(List<KeyCode> keyCodes) {
        bool keyHasBeenPressed = false;

        while (true) {
            foreach (KeyCode keyCode in keyCodes) {
                if (Input.GetKeyDown(keyCode)) {
                    keyHasBeenPressed = true;
                }
            }
            if (keyHasBeenPressed) {
                break;
            }
            yield return null;
        }
    }

    public ChoiceButton choiceButtonPrefab;
    public RectTransform choicePanel;
    IEnumerator ShowChoice(List<string> choices, List<string> labels) {
        choicePanel.GetComponent<CanvasGroup>().alpha = 1;
        choicePanel.GetComponent<CanvasGroup>().blocksRaycasts = true;
        choicePanel.GetComponent<CanvasGroup>().interactable = true;

        GameObject[] children = new GameObject[choicePanel.transform.childCount];

        for (int i = 0; i < choicePanel.transform.childCount; i++) {
            children[i] = choicePanel.transform.GetChild(i).gameObject;
        }

        foreach (GameObject child in children) {
            DestroyImmediate(child.gameObject);
        }

        bool choiceMade = false;
        int choice = -1;
        for (int i = 0; i < choices.Count; i++) {

            if (choices[i][0] == '[') {
                string[] choiceSplit = choices[i].Split(']');
                string choiceRequirement = choiceSplit[0].Substring(1);

                if (choiceRequirement.StartsWith("deviance")) {
                    string deviantCount = choiceRequirement.Remove(0, 8);
                    int deviance = int.Parse(deviantCount);
                    if (GameManager.instance.devianceController.level < deviance) {
                        continue;
                    }
                }
                else if (!GameManager.instance.inventory.Contains(choiceRequirement.ToLower())) {
                    continue;
                }

                choices[i] = choiceSplit[1];
            }

            ChoiceButton newButton = Instantiate<ChoiceButton>(choiceButtonPrefab);
            newButton.SetText(choices[i]);
            newButton.index = i;
            newButton.transform.SetParent(choicePanel.transform);
            newButton.SetButtonEvent(() => {
                choice = newButton.index;
                choiceMade = true;
            });
        }

        while (!choiceMade) {
            yield return null;
        }

        Debug.Log("Choice made:" + choice.ToString());
        if (!string.IsNullOrWhiteSpace(labels[choice])) {
            labelJump = labels[choice];
        }
        choicePanel.GetComponent<CanvasGroup>().alpha = 0;
        choicePanel.GetComponent<CanvasGroup>().blocksRaycasts = false;
        choicePanel.GetComponent<CanvasGroup>().interactable = false;
    }
}
