using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System.Linq;

public class ScrollViewScript : MonoBehaviour {
    private const string newQuestionAnswerLineDefault = "???? - ????";
    public GameObject answerlineQuestionPrefab;
    public Transform contentPanel;
    public Transform newQuestionsPanel;

    private int newQuestionSiblingIndex;
    private bool answeredCorrectly;
    private List<KeyValuePair<string, int>> players;
    private int gameId;
    private string gameMode;

    private bool sizeUpdated = false;
    StatsScript statsScript;
    GameManagerScript gameManagerScript;
    TimerScript ts;

    InformationPanelScript ips;

    public string currentPlayer;

    // Start is called before the first frame update
    void Start() {
        statsScript = GameObject.Find("StatsPanel").GetComponent<StatsScript>();
        gameManagerScript = GameObject.Find("GameManager").GetComponent<GameManagerScript>();
        ts = GameObject.Find("TimerCircle").GetComponent<TimerScript>();
        players = gameManagerScript.GetPlayers();

        EventManager.StartListening("TimerEvent", TimerRunOutEvent);
        gameId = gameManagerScript.GameId;
        currentPlayer = Database.Instance.GetCurrentPlayer(gameId, GetGameMode());

        statsScript.MakeBold(currentPlayer);

        KeyValuePair<int, string> signedInUser = Database.Instance.GetSignedInUser();
        
        List<NewQuestionData> answerlineQuestions;
        if (gameMode.Equals(Constants.ONLINE)) {
            answerlineQuestions = Database.Instance.GetPlayerQuestions(gameId, signedInUser.Value, GetGameMode());
        } else {
            answerlineQuestions = Database.Instance.GetPlayerQuestions(gameId, currentPlayer, GetGameMode());
        }
        if (Database.Instance.GetRoundValue(gameId, GetGameMode()) > 1) {
            SetQuestionsInAnswerLine(answerlineQuestions);
        }

        statsScript.SetQuestionsLost(Database.Instance.GetQuestionsLost(gameId, currentPlayer, GetGameMode()));
    }

    private void Update() {
        if (!sizeUpdated){
            UpdateAnswerlineCardSize();
        }
    }

    public string GetGameMode() {
        if (gameMode == null) {
            gameMode = PlayerPrefs.GetString(Constants.GAME_MODE);
        }
        return gameMode;
    }

[SerializeField] GameObject leftDropZone;
[SerializeField] GameObject rightDropZone;
[SerializeField] GameObject middleDropZone;
    public void SetQuestionsInAnswerLine(List<NewQuestionData> questions) {
        int i = 0;

        RectTransform newQuestionRect = GameObject.Find("NewQuestion").GetComponent<RectTransform>();
        GameObject ldz = Instantiate(leftDropZone,Vector2.zero, Quaternion.identity);
        GameObject rdz = Instantiate(rightDropZone,Vector2.zero, Quaternion.identity);
        ldz.transform.SetParent(contentPanel);
        ldz.transform.SetSiblingIndex(i++);
        ldz.transform.localScale = new Vector3(1,1,1);
        if (newQuestionRect.rect.width < 50f) {
            ldz.GetComponent<LayoutElement>().preferredWidth = 50f;
        } else {
            ldz.GetComponent<LayoutElement>().preferredWidth = newQuestionRect.rect.width;
        }

        KeyValuePair<int, string> signedInUser = Database.Instance.GetSignedInUser();
        foreach (NewQuestionData q in questions) {
            GameObject answerLineQuestion = Instantiate(answerlineQuestionPrefab, Vector3.zero, Quaternion.identity);
            answerLineQuestion.transform.SetParent(contentPanel, false);
            answerLineQuestion.transform.SetSiblingIndex(i++);
            answerLineQuestion.transform.localScale = new Vector3(1,1,1);
            answerLineQuestion.GetComponent<LayoutElement>().preferredWidth = newQuestionRect.rect.width;
            answerLineQuestion.GetComponent<LayoutElement>().preferredHeight = newQuestionRect.rect.height;

            QuestionCard answerLineQuestionCard = answerLineQuestion.GetComponent<QuestionCard>();
            answerLineQuestionCard.SetAnswerText(q.Answer);
            answerLineQuestionCard.SetQuestionText(q.Question);
            answerLineQuestionCard.SetId(q.Id);
            answerLineQuestionCard.SetQuestionSafe(q.QuestionSafe);
            answerLineQuestionCard.SetBackCategoryText(q.CategoryName);
            answerLineQuestionCard.SetQuestionCategoryColor(q.CategoryColor);

            if (gameMode.Equals(Constants.ONLINE)) {
                if (signedInUser.Value.Equals(Database.Instance.GetSignedInUser().Value, StringComparison.InvariantCultureIgnoreCase)) {
                    answerLineQuestionCard.SetFrostingActive(false);
                } else {
                    answerLineQuestionCard.SetFrostingActive(true);
                }
            }

            GameObject mdz = Instantiate(middleDropZone, Vector3.zero, Quaternion.identity);
            mdz.transform.SetParent(contentPanel);
            mdz.transform.SetSiblingIndex(i++);
            mdz.transform.localScale = new Vector3(1,1,1);
        }

        NewDropZoneScript newDropZoneScript = contentPanel.GetChild(i-1).GetComponent<NewDropZoneScript>();
        Destroy(newDropZoneScript.gameObject);

        rdz.transform.SetParent(contentPanel);
        rdz.transform.SetSiblingIndex(i);
        rdz.transform.localScale = new Vector3(1,1,1);
        if (newQuestionRect.rect.width < 50f) {
            rdz.GetComponent<LayoutElement>().preferredWidth = 50f;
        } else {
            rdz.GetComponent<LayoutElement>().preferredWidth = newQuestionRect.rect.width;
        }
        SetAllQuestionsLocked(false);
    }

    internal void SetQuestionsFrosted(bool frost) {
        List<QuestionCard> questions = contentPanel.GetComponentsInChildren<QuestionCard>().ToList();
        questions.ForEach(q => q.SetFrostingActive(frost));
    }

    private void UpdateAnswerlineCardSize() {
        RectTransform newQuestionRect = GameObject.Find("NewQuestion").GetComponent<RectTransform>();
        List<QuestionCard> questions = contentPanel.GetComponentsInChildren<QuestionCard>().ToList();

        foreach (QuestionCard q in questions) {
            q.GetComponent<LayoutElement>().preferredWidth = newQuestionRect.rect.width;
            q.GetComponent<LayoutElement>().preferredHeight = newQuestionRect.rect.height;
        }

        if (contentPanel.childCount > 0) {
            contentPanel.GetChild(0).GetComponent<LayoutElement>().preferredWidth = newQuestionRect.rect.width;
            contentPanel.GetChild(contentPanel.childCount -1).GetComponent<LayoutElement>().preferredWidth = newQuestionRect.rect.width;
        }

        if (questions.Count > 0 && questions[0].GetComponent<LayoutElement>().preferredWidth >= 0) {
            sizeUpdated = true;
        }
    }

    public int GetUnlockedQuestionCount() {
        return contentPanel.GetComponentsInChildren<QuestionCard>().Where(q => !q.IsQuestionSafe()).ToArray().Length;;
    }

    public void SetAllQuestionsLocked(bool needsSave) {
        List<int> saveQuestions = new List<int>();
        AnswerLineQuestionCard[] answerLineQuestionCards = contentPanel.GetComponentsInChildren<AnswerLineQuestionCard>();
        foreach (var questionCard in answerLineQuestionCards)
        {
            if (needsSave && !questionCard.IsQuestionSafe()) {
                saveQuestions.Add(questionCard.QuestionId);
                questionCard.SetQuestionSafe();
            }
        }

        if (saveQuestions.Count > 0) {
            Database.Instance.SavePlayersQuestion(saveQuestions, GameManagerScript.GetCurrentPlayer(), gameId, GetGameMode());
        }
    }

     public List<int> GetQuestionIdsInAnswerLine() {
        List<int> questionIds = new List<int>();

        foreach (AnswerLineQuestionCard q in contentPanel.GetComponentsInChildren<AnswerLineQuestionCard>()) {
            questionIds.Add(q.QuestionId);
        }

        return questionIds;
    }

    public void RemoveEverythingFromAnswerline() {
        foreach (Transform child in contentPanel.transform) {
            Destroy(child.gameObject);
        }
    }

    public void RemoveUnlockedQuestions() {
        int lostQuestions = 0;
        AnswerLineQuestionCard[] answerLineQuestionCards = contentPanel.GetComponentsInChildren<AnswerLineQuestionCard>();

        foreach (AnswerLineQuestionCard aq in answerLineQuestionCards)
        {
            if (!aq.IsQuestionSafe()){
                lostQuestions++;
                aq.transform.SetParent(null);
                Destroy(aq);
                Destroy(aq.gameObject);
            }
        }
        gameManagerScript.UpdateQuestiosLost(lostQuestions, currentPlayer);
        statsScript.SetQuestionsInAnswerLine(currentPlayer, contentPanel.GetComponentsInChildren<AnswerLineQuestionCard>().Length);
    }

 

    void TimerRunOutEvent() { // Should be moved to some gameController
        ts.StopTimer();
        GenericDialog dialog = GenericDialog.Instance();
        string message = LocalizationManager.Instance.GetText("TIMER_DIALOG_MESSAGE");
        dialog.SetTitle(LocalizationManager.Instance.GetText("TIMER_DIALOG_TITLE"));
        dialog.SetMessage(String.Format(message, GetUnlockedQuestionCount()));
        dialog.SetOnAccept(LocalizationManager.Instance.GetText("OK"), () => {
            RemoveUnlockedQuestions();
            ts.ResetTimer();
            dialog.Hide();
            NextPlayer();
        });
        dialog.SetOnDecline("", () => dialog.Hide());
        dialog.Show();

    }

    public void NextPlayer() {
        for (int i = 0; i < players.Count; i++) {
            if (players[i].Key.Equals(currentPlayer, StringComparison.InvariantCultureIgnoreCase)) {
                if (i + 1 < players.Count) {
                    currentPlayer = players[i + 1].Key;
                    break;
                } else {
                    currentPlayer = players[0].Key;
                    statsScript.IncreaseRoundValue();
                    break;
                }
            }
        }
        
        GenericDialog dialog = GenericDialog.Instance();
        dialog.SetTitle(LocalizationManager.Instance.GetText("NEXT_PLAYER_DIALOG_TITLE"));
        string message = LocalizationManager.Instance.GetText("NEXT_PLAYER_DIALOG_MESSAGE");
        dialog.SetMessage(String.Format(message, currentPlayer));
        dialog.SetOnAccept(LocalizationManager.Instance.GetText("OK"), () => {
            RemoveEverythingFromAnswerline();
            List<NewQuestionData> questions = Database.Instance.GetPlayerQuestions(gameId, currentPlayer, GetGameMode());
            SetQuestionsInAnswerLine(questions);

            statsScript.SetQuestionsLost(Database.Instance.GetQuestionsLost(gameManagerScript.GameId, currentPlayer, GetGameMode()));

            statsScript.MakeBold(currentPlayer);
            Database.Instance.SetCurrentPlayer(gameId, currentPlayer, GetGameMode());
            dialog.Hide();
        });
        dialog.SetOnDecline("", () => dialog.Hide());
        dialog.Show();
    }
}
