using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Firebase.Database;
using TMPro;
using UnityEngine;

public class VotingPage : MonoBehaviour
{
    [Header("Scene References")]
    public PropositionFrame proposition1;
    public PropositionFrame proposition2;
    public TextMeshProUGUI currentPromptLabel;
    public TextMeshProUGUI timerLabel;

    [Header("Asset References")]
    public PromptList promptList;

    [Header("Settings")]
    public float votingTime = 20;

    private Queue<Question> remainingQuestions = new Queue<Question>();
    private Question currentQuestion = null;

    private DatabaseReference roomRef;
    private Dictionary<string, Player> currentPlayers; //all the current playing players

    private DateTime endOfTimer = DateTime.MinValue;

    private Action OnVoteEnded;


    private void Update()
    {
        //there is no question displayed or timer is not started
        if (currentQuestion == null || endOfTimer == DateTime.MinValue)
            return;


        if (DateTime.Now < endOfTimer)
        {
            TimeSpan duration = endOfTimer - DateTime.Now;
            timerLabel.text = ((int)duration.TotalSeconds).ToString("D2");
        }
        else
        {
            timerLabel.text = "0";
            if (remainingQuestions.Count > 0)
            {
                currentQuestion = remainingQuestions.Dequeue();
                ShowQuestion();
            }
            else
            {
                OnVoteEnded?.Invoke();
                OnVoteEnded = null;
                gameObject.SetActive(false);
            }
        }
    }


    // Start is called before the first frame update
    public void ShowVotingPage(DatabaseReference _roomRef, Dictionary<string, Player> _currentPlayers, Dictionary<int, Question> _questions, Action _callback_OnVoteEnded)
    {
        Debug.Log("Initializing voting page");
        this.gameObject.SetActive(true);
        roomRef = _roomRef;
        currentPlayers = _currentPlayers;
        OnVoteEnded = _callback_OnVoteEnded;

        Question[] _questionArray = _questions.Values.ToArray();

        for (int i = 0; i < _questionArray.Length; i++)
        {
            remainingQuestions.Enqueue(_questionArray[i]);
            roomRef.Child("questions").Child(i.ToString()).ValueChanged += OnQuestionChanged;
        }

        currentQuestion = remainingQuestions.Dequeue();
        ShowQuestion();
    }

    /// <summary>
    /// Display next question on screen
    /// </summary>
    void ShowQuestion()
    {
        roomRef.Child("currentQuestionId").SetValueAsync(currentQuestion.index);

        Debug.Log($"Show Question {currentQuestion.promptId}", this);
        Prompt currentPrompt = promptList.GetPromptById(currentQuestion.promptId);
        currentPromptLabel.text = currentPrompt.en;

        Debug.Log($"Prompt is {currentPromptLabel.text}", this);

        if (currentQuestion.propositions[0] != null)
            proposition1.Initialize(currentQuestion.propositions[0]);
        else
        {
            Debug.Log("User has given no proposition", this);
            //manage if there is no proposition
        }

        if (currentQuestion.propositions[1] != null)
            proposition2.Initialize(currentQuestion.propositions[1]);
        else
        {
            Debug.Log("User has given no proposition", this);
            //manage if there is no proposition
        }

        endOfTimer = DateTime.Now.AddSeconds(votingTime);
    }

    /// <summary>
    /// Is called when a question is updated (someone has voted)
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="_questionRef"></param>
    private void OnQuestionChanged(object sender, ValueChangedEventArgs _questionRef)
    {
        //Debug.Log("a question value has changed, maybe someone has voted", this);
        string JSON = _questionRef.Snapshot.GetRawJsonValue();
        Question question = Newtonsoft.Json.JsonConvert.DeserializeObject<Question>(JSON);

        //if someone succeeded to vote for another question than the one that is displayed => yeet
        if (question.index != currentQuestion.index)
            return;

        //Debug.Log($"someone has voted for {question.index}", this);
        currentQuestion.propositions = question.propositions;
        UpdateVoters();

    }

    private void UpdateVoters()
    {
        if (currentQuestion.propositions.Count == 0) //manage if there is no propositons
            return;

        if (currentQuestion.propositions[0] != null)
        {
            List<Player> playersThatHasVotedForFirstProposition = new List<Player>();
            if (currentQuestion.propositions[0].voters != null)
            {
                foreach (string playerId in currentQuestion.propositions[0].voters)
                {
                    playersThatHasVotedForFirstProposition.Add(currentPlayers[playerId]);
                }
                proposition1.UpdateVoters(playersThatHasVotedForFirstProposition);
            }
        }

        if (currentQuestion.propositions[1] != null)
        {
            List<Player> playersThatHasVotedForSecondProposition = new List<Player>();
            if (currentQuestion.propositions[1].voters != null)
            {
                foreach (string playerId in currentQuestion.propositions[1].voters)
                {
                    playersThatHasVotedForSecondProposition.Add(currentPlayers[playerId]);
                }
                proposition2.UpdateVoters(playersThatHasVotedForSecondProposition);
            }
        }
    }
}
