﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using PlayFab;
using PlayFab.ClientModels;

public class PlayerStats : MonoBehaviour {

    [Header("UI References")]
    #region
    [SerializeField] TMP_Text m_firstPlaceWinsText;
    [SerializeField] TMP_Text m_secondPlaceWinsText;
    [SerializeField] TMP_Text m_thirdPlaceWinsText;
    [SerializeField] TMP_Text m_totalRacesText;
    #endregion

    [Header("Received Stats")]
    #region
    [SerializeField] Vector2 m_playerTimes = Vector2.zero;
    [SerializeField] bool m_recievedTimes = false;
    #endregion

    [Header("Debug")]
    #region
    [SerializeField] DebugChannelSO m_debugChannel;
    #endregion

    // PRIVATE VARIABLES //
    #region
    int m_firstPlaceWins 
    { 
        set
        {
            if (m_firstPlaceWinsText)
                m_firstPlaceWinsText.SetText(value.ToString());

            if (m_debugChannel)
                m_debugChannel.Raise(this, "First Place Wins set to " + value);
        }
    }
    int m_secondPlaceWins
    {
        set
        {
            if (m_secondPlaceWinsText)
                m_secondPlaceWinsText.SetText(value.ToString());

            if (m_debugChannel)
                m_debugChannel.Raise(this, "Second Place Wins set to " + value);
        }
    }
    int m_thirdPlaceWins
    {
        set
        {
            if (m_thirdPlaceWinsText)
                m_thirdPlaceWinsText.SetText(value.ToString());

            if (m_debugChannel)
                m_debugChannel.Raise(this, "Third Place Wins set to " + value);
        }
    }
    int m_totalRaces
    {
        set
        {
            if (m_totalRacesText)
                m_totalRacesText.SetText(value.ToString());

            if (m_debugChannel)
                m_debugChannel.Raise(this, "Total Races set to " + value);
        }
    }
    static string m_tempTrackName = "";
    #endregion

    void CheckBestPlayerTimes(string _trackName)
    {
        m_recievedTimes = false;
        m_playerTimes = Vector2.zero;
        m_tempTrackName = "";
        m_tempTrackName = _trackName;

        if(m_tempTrackName == "")
        {
            if (m_debugChannel)
                m_debugChannel.Raise(this, "Track name is Empty");

            m_recievedTimes = true;

            return;
        }

        var _request = new GetUserDataRequest { };

        PlayFabClientAPI.GetUserData(_request, GetPlayerTimes, result => Debug.Log("["+ typeof(PlayFabClientAPI).ToString() +"] Error on request: " + result.ErrorMessage));
    }
    public void GetPlayerStats() 
    {
        PlayFabClientAPI.GetPlayerStatistics(
            new GetPlayerStatisticsRequest(),
            UpdatePlayerStatSheet,
            error => Debug.LogError(error.GenerateErrorReport())
        );
    }

    void GetPlayerTimes(GetUserDataResult _result)
    {
        if (m_tempTrackName == "")
        {
            if (m_debugChannel)
                m_debugChannel.Raise(this, "Track name is Empty");

            m_recievedTimes = true;

            return;
        }

        float _lapTime = 0f;
        float _raceTime = 0f;

        string _lapTimeKey = m_tempTrackName + "_bestLapTime";
        string _raceTimeKey = m_tempTrackName + "_bestRaceTime";

        string _bestLapTime = "";
        string _bestRaceTime = "";


        if (_result.Data.ContainsKey(_lapTimeKey))
        {
            _bestLapTime = _result.Data[_lapTimeKey].Value;
            float.TryParse(_bestLapTime, out _lapTime);
        }

        if (_result.Data.ContainsKey(_raceTimeKey))
        {
            _bestRaceTime = _result.Data[_raceTimeKey].Value;
            float.TryParse(_bestRaceTime, out _raceTime);
        }

        m_playerTimes = new Vector2(_lapTime, _raceTime);

        if (m_debugChannel)
            m_debugChannel.Raise(this, "Current Times { " + _lapTimeKey + ": " + _bestLapTime + ", " + _raceTimeKey + ": " + _bestRaceTime + " }");

        m_recievedTimes = true;
    }
    private void UpdatePlayerStatSheet(GetPlayerStatisticsResult _obj) 
    {
        List<StatisticValue> _stats = _obj.Statistics;

        foreach (StatisticValue _stat in _stats)
        {
            switch (_stat.StatisticName)
            {
                case "1st Place Wins":
                    m_firstPlaceWins = _stat.Value;
                    break;
                case "2nd Place Wins":
                    m_secondPlaceWins = _stat.Value;
                    break;
                case "3rd Place Wins":
                    m_thirdPlaceWins = _stat.Value;
                    break;
                case "Total Races":
                    m_totalRaces = _stat.Value;
                    break;
                default:
                    break;
            }
        }
    }

    public void ComparePlayerTimes (string _trackName, float _lapTime, float _raceTime)
    {
        StartCoroutine(WaitForTimeResults(_trackName, _lapTime, _raceTime));
    }
    IEnumerator WaitForTimeResults (string _trackName, float _lapTime, float _raceTime)
    {
        CheckBestPlayerTimes(_trackName);

        while (!m_recievedTimes)
        {
            yield return new WaitForSeconds(0.1f);
        }

        m_recievedTimes = false;

        Vector2 oldTimes = m_playerTimes;
        m_playerTimes = Vector2.zero;

        if (_lapTime >= oldTimes.x && _lapTime != 0f && oldTimes.x != 0f)
        {
            if (m_debugChannel)
                m_debugChannel.Raise(this, _trackName + " Lap Time Unchanged");
            _lapTime = (int)oldTimes.x;
        }
        else
        {
            if (m_debugChannel)
                m_debugChannel.Raise(this, _trackName + " Lap Time Updated");
        }

        if (_raceTime >= oldTimes.y && _raceTime != 0f && oldTimes.y != 0f)
        {
            if (m_debugChannel)
                m_debugChannel.Raise(this, _trackName + " Race Time Unchanged");
            _raceTime = (int)oldTimes.y;
        }
        else
        {
            if (m_debugChannel)
                m_debugChannel.Raise(this, _trackName + " Race Time Updated");
        }

        if (m_debugChannel)
            m_debugChannel.Raise(this, "New Times: " + _lapTime.ToString() + ", " + _raceTime.ToString());

        PlayfabCloudScriptAPI.UpdateBestTimes(_trackName, _lapTime, _raceTime);

        yield return null;
    }
}
