using System.Collections;
using System.Collections.Generic;
using System.IO;
using System;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class GameController : MonoBehaviour
{
    // All of the words that can be used in this session
    private string[] words;

    // Where we currently are in the word
    private int letterIndex;

    // Where we currently are in the word list
    private int wordIndex;

    // The word that is currently being spelled
    private string currentWord;

    // All of the available themes
    private ThemeList themeList;

    // The theme we are currently using
    private Theme currentTheme;

    // The input field for testing purposes
    public TMP_InputField input;

    // Current value of timer in seconds
    private float timerValue;

    // "Game over" or "You win!"
    public TMP_Text endText;

    // First score display
    public TMP_Text correctWordsText;

    // Second score display
    public TMP_Text correctLettersText;

    // The game over panel
    public GameObject gameEndedPanel;

    // Button for restarting the game
    public Button replayButton;

    // Indicates if the game is still going
    private bool gameEnded;

    // Amount of seconds user gets per letter of the current word
    // Set to 1 for testing; should be increased later
    private int secondsPerLetter = 1;

    // Counter that keeps track of how many words have been spelled correctly
    private int spelledLetters;

    // Counter that keeps track of how many letters have been spelled correctly
    private int spelledWords;

    [Header("Letter prefab")]
    // Letter prefab
    public GameObject letterPrefab;
    
    [Header("UI References")]
    // Reference to letter prefab
    public Transform letterContainer;
    // The Image component for displaying the appropriate sprite
    public Image wordImage;
    // Timer display
    public TMP_Text timerText;

    [Header("private variables")]
    // The GameObjects representing the letters
    private List<GameObject> letters = new List<GameObject>();


    // Start is called before the first frame update
    public void Start()
    {
        spelledLetters = 0;
        // We use -1 instead of 0 so SetNextWord can simply increment it each time
        spelledWords = -1;
        gameEnded = false;
        wordIndex = 0;
        input.text = "";
        timerValue = 0.0f;
        gameEndedPanel.SetActive(false);
        replayButton.onClick.AddListener(Start);

        // TODO: change to ScriptableObject
        themeList = ThemeLoader.LoadJson();
        currentTheme = FindThemeByName(PlayerPrefs.GetString("themeName"));
        words = currentTheme.words;
        ShuffleWords();
        SetNextWord();
    }

    // Update is called once per frame
    public void Update()
    {
        if (!gameEnded)
        {
            if (input.text.Length > 0)
            {
                CheckChar(input.text[0]);
            }

            timerValue -= Time.deltaTime;

            if (timerValue <= 0.0f)
            {
                timerValue = 0.0f;
                ActivateGameOver();
            }

            int minutes = Mathf.FloorToInt(timerValue / 60.0f);
            int seconds = Mathf.FloorToInt(timerValue % 60.0f);

            timerText.text = string.Format("{0:00}:{1:00}", minutes, seconds);
        }
    }

    // Randomly shuffle the list of words
    private void ShuffleWords()
    {
        for (int i = words.Length - 1; i > 0; i--)
        {
            // Generate a random index between 0 and i (inclusive)
            int j = UnityEngine.Random.Range(0, i + 1);

            // Swap the values at indices i and j
            (words[j], words[i]) = (words[i], words[j]);
        }
    }

    // Displays the game over panel and score values
    private void ActivateGameOver()
    {
        DeleteWord();
        endText.text = "GAME OVER";
        correctLettersText.text = "Correctly spelled letters: " + spelledLetters.ToString();
        correctWordsText.text = "Correctly spelled words: " + spelledWords.ToString();

        gameEndedPanel.SetActive(true);
        gameEndedPanel.transform.SetAsLastSibling();

        gameEnded = true;
    }

    // Display win screen
    private void ActivateWin()
    {
        DeleteWord();
        endText.text = "YOU WIN!";
        correctLettersText.text = "Your time: " + spelledLetters.ToString();
        int totalWordsDuration = 0;

        foreach (string word in words)
        {
            totalWordsDuration += word.Length * secondsPerLetter + 1;
        }

        // How much time was spent by the player
        int spentTime = totalWordsDuration - (int)timerValue;

        int seconds = spentTime % 60;
        int minutes = spentTime / 60;

        if (minutes == 0)
        {
            correctLettersText.text = "Your time: " + seconds + " seconds";
        }
        else
        {
            correctLettersText.text = "Your time: " + minutes + " minutes and " + seconds + " seconds";
        }

        correctWordsText.text = "";

        gameEndedPanel.SetActive(true);
        gameEndedPanel.transform.SetAsLastSibling();

        gameEnded = true;
    }

    // Check if the correct char has been given as input
    private void CheckChar(char letter)
    {
        if (Char.ToUpper(letter) == Char.ToUpper(currentWord[letterIndex]) && input.text.Length == 1)
        {
            letters[letterIndex].GetComponent<Image>().color = Color.green;
            input.text = "";
            spelledLetters++;
            letterIndex++;

            if (letterIndex >= currentWord.Length)
            {
                DeleteWord();
                StartCoroutine(Wait());
                SetNextWord();
            }
        }
    }

    // Delete all letter objects
    private void DeleteWord()
    {
        for (int i = 0; i < currentWord.Length; i++)
        {
            Destroy(letters[i]);
        }
        letters.Clear();
    }

    // Adds seconds to timer
    private void AddSeconds(int seconds)
    {
        timerValue += (float)seconds;
    }

    // Find the chosen theme by its name
    private Theme FindThemeByName(string themeName)
    {
        int themeIndex = 0;

        while (themeIndex < themeList.themes.Length)
        {
            Theme theme = themeList.themes[themeIndex];
            if (theme.name == themeName)
            {
                return theme;
            }
            themeIndex++;
        }

        Debug.Log("Requested theme not found");
        return null;
    }

    // Display next word in the series
    private void SetNextWord()
    {
        spelledWords++;

        if (wordIndex < words.Length)
        {
            currentWord = words[wordIndex];

            ChangeSprite(currentWord);
            DisplayWord(currentWord);
            AddSeconds(currentWord.Length * secondsPerLetter + 1);

            letterIndex = 0;
            wordIndex++;
        }
        else
        {
            ActivateWin();
        }
    }

    // Displays the word that needs to be spelled
    private void DisplayWord(string word)
    {
        for (int i = 0; i < word.Length; i++)
        {
            // Create instance of prefab
            GameObject instance = GameObject.Instantiate(letterPrefab, letterContainer);
            letters.Add(instance);

            // Dynamically load appearance
            Image background = instance.GetComponent<Image>();
            background.color = Color.red;
            TMP_Text txt = instance.GetComponentInChildren<TMP_Text>();
            txt.text = Char.ToString(Char.ToUpper(word[i]));
        }
    }

    // Change the image that is being displayed
    private void ChangeSprite(string spriteName)
    {
        // Load the new sprite from the Resources folder
        Sprite sprite = Resources.Load<Sprite>("SpellingBee/images/" + spriteName);

        // Set the new sprite as the Image component's source image
        wordImage.sprite = sprite;
    }

    private IEnumerator Wait()
    {
        yield return new WaitForSecondsRealtime(2);
    }
}
