using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using PlayFab;
using PlayFab.ClientModels;
using TMPro;
using UnityEngine.UI;
using System.Linq;

public class WeekendTournamentDisplay : MonoBehaviour {

    public GameObject countDownUI;
    public TextMeshProUGUI countDownStart;
    public TextMeshProUGUI tournamentText;
    public Slider countdownSlider;

    public GameObject tournamentDataUI;
    public TextMeshProUGUI tournamentXP;
    public TextMeshProUGUI tournamentPosition;
    DateTime ClockInfoUTC;

    public bool debugMode = false;
    public float addDays;
    public float addHours;

    public float hoursToAddToUTC = 4;

    void OnEnable() {
        BeginWeekendTournamentDisplay();
    }

    void BeginWeekendTournamentDisplay() {
        ClockInfoUTC = DateTime.UtcNow;
        if (debugMode) {
            Debug.Log("it is really: " + ClockInfoUTC + " UTC right now");
            ClockInfoUTC = GetNextWeekday(ClockInfoUTC.Date, DayOfWeek.Saturday).AddDays(addDays).AddHours(addHours + hoursToAddToUTC);
            Debug.Log("we're gonna behave like it's: " + ClockInfoUTC + " UTC");
            Debug.Log("which is " + ClockInfoUTC.AddHours(-4) + " EST");
        }

        bool holiday = false;
        bool tournament = false;
        string holidayText = "";
        DateTime startDate = DateTime.MinValue;

        DayOfWeek weekDay = ClockInfoUTC.DayOfWeek;

        switch (ClockInfoUTC.Month) {
            case 8:
            case 7:
                DateTime specialThursdayStartTime = new DateTime(2019, 8, 1, (int)hoursToAddToUTC + 19, 30, 00);
                DateTime specialThursdayEndTime = new DateTime(2019, 8, 2, (int)hoursToAddToUTC + 0, 00, 00);
                if ((specialThursdayStartTime.DayOfYear - ClockInfoUTC.DayOfYear) < 4 && 0 > ClockInfoUTC.CompareTo(specialThursdayEndTime)) {
                    startDate = specialThursdayStartTime;
                    holidayText = "Evening";
                    holiday = true;
                    if (0 <= ClockInfoUTC.CompareTo(specialThursdayStartTime)) {
                        tournament = true;
                    }
                }
                break;
            case 11:
                int thanksgiving = (from day in Enumerable.Range(1, 30)
                                    where new DateTime(ClockInfoUTC.Year, 11, day).DayOfWeek == DayOfWeek.Thursday
                                    select day).ElementAt(3);
                DateTime thanksgivingDay = new DateTime(ClockInfoUTC.Year, 11, thanksgiving);
                thanksgivingDay = thanksgivingDay.AddHours(hoursToAddToUTC);

                // the thanksgiving tournamnet starts the wednesday before
                DateTime thanksgivingTournamentStartDate = thanksgivingDay.AddDays(-1);

                if (thanksgivingTournamentStartDate.DayOfYear - ClockInfoUTC.DayOfYear <= 4 && (thanksgivingTournamentStartDate.DayOfYear + 4 - ClockInfoUTC.DayOfYear) > 0) {
                    startDate = thanksgivingTournamentStartDate;
                    holidayText = "Thanksgiving";
                    holiday = true;
                    if (
                            // 7 days from the start date of the tournament until
                            (
                                (
                                    ClockInfoUTC.Day >= 27 &&
                                    ClockInfoUTC.Day <= 30
                                )
                                ||
                                (
                                    ClockInfoUTC.Day >= 1 &&
                                    ClockInfoUTC.Day <= 3
                                )
                            )
                            &&

                            // on these specific days
                            (
                                // starting wednesday at midnight
                                (
                                    ClockInfoUTC.DayOfWeek == DayOfWeek.Wednesday &&
                                    ClockInfoUTC.Hour >= hoursToAddToUTC
                                )
                                ||
                                // through the thursday, friday, saturday, and sunday
                                ClockInfoUTC.DayOfWeek == DayOfWeek.Thursday ||
                                ClockInfoUTC.DayOfWeek == DayOfWeek.Friday ||
                                ClockInfoUTC.DayOfWeek == DayOfWeek.Saturday ||
                                ClockInfoUTC.DayOfWeek == DayOfWeek.Sunday ||
                                // until midnight monday 
                                (
                                    ClockInfoUTC.DayOfWeek == DayOfWeek.Monday &&
                                    ClockInfoUTC.Hour < hoursToAddToUTC
                                )
                            )
                       ) {
                        tournament = true;
                    }
                }

                break;
        }

        if (holiday) {
            tournamentText.text = holidayText + " Tournament";
            if (tournament) {
                ShowTournamentData(holidayText);
            }
            else {
                ShowCountdownToWeekend(holidayText, startDate);
            }
            return;
        }

        int currentDay = (int)ClockInfoUTC.DayOfWeek;
        switch (currentDay) {
            case 0:
                ShowTournamentData();
                break;
            case 1:
                if (ClockInfoUTC.Hour < hoursToAddToUTC) {
                    ShowTournamentData();
                }
                else {
                    ShowCountdownToWeekend();
                }
                break;
            case 6:
                if (ClockInfoUTC.Hour >= hoursToAddToUTC) {
                    ShowTournamentData();
                }
                else {
                    ShowCountdownToWeekend();
                }
                break;
            case 5:
            case 2:
            case 3:
            case 4:
                ShowCountdownToWeekend();
                break;
        }
    }

    void WeekendTournamentStarted(string specialTournamentText = "") {
        if (!countDownUI) {
            return;
        }
        TextMeshProUGUI headerText = countDownUI.GetComponent<TextMeshProUGUI>();
        if (specialTournamentText != "") {
            headerText.text = specialTournamentText + " \nTournament\nStarted!";
        }
        else {
            headerText.text = "Weekend \nTournament\nStarted!";
        }

        countDownUI.SetActive(true);

        foreach (Transform child in countDownUI.transform) {
            child.gameObject.SetActive(false);
        }
    }

    public void ShowTournamentData(string specialTournamentText = "") {
        if (!tournamentDataUI) {
            WeekendTournamentStarted(specialTournamentText);
            return;
        }

        PlayFabClientAPI.GetLeaderboardAroundPlayer(new GetLeaderboardAroundPlayerRequest() { StatisticName = "WeekendTournamentWins", MaxResultsCount = 1 }, results => {
            if (results != null && results.Leaderboard != null) {
                foreach (PlayerLeaderboardEntry entry in results.Leaderboard) {
                    if (entry.PlayFabId == PersistentData.localPlayerData.playFabId) {
                        tournamentPosition.text = "Position #" + (entry.Position + 1);
                        tournamentXP.text = entry.StatValue + " wins";

                        tournamentDataUI.SetActive(true);
                        break;
                    }
                }
            }
        }, null);
    }

    public void ShowCountdownToWeekend(string specialTournamentText = "", DateTime start = default(DateTime)) {
        int daysRemaining;
        int hoursRemaining;
        int minutesRemaining = 0;

        DateTime startTime;

        if (specialTournamentText != "") {
            startTime = start;
        }
        else {
            startTime = GetNextWeekday(ClockInfoUTC.Date, DayOfWeek.Saturday).AddHours(hoursToAddToUTC);
        }

        //Debug.Log("Next Start: " + startTime);

        string displayString = "starts in\n";

        TimeSpan timespan = startTime - ClockInfoUTC;
        daysRemaining = timespan.Days;
        if (daysRemaining > 0) {
            if (daysRemaining > 1)
                displayString += daysRemaining + " days ";
            else
                displayString += daysRemaining + " day ";
        }
        else {
            if (specialTournamentText != "") {
                StartCoroutine(TickingCountdown(specialTournamentText, startTime));
            }
            else {
                StartCoroutine(TickingCountdown());
            }
        }

        hoursRemaining = timespan.Hours;
        if (hoursRemaining > 0) {
            if (hoursRemaining > 1)
                displayString += hoursRemaining + " hours ";
            else
                displayString += hoursRemaining + " hour ";
        }

        if (daysRemaining <= 0 && hoursRemaining <= 0) {
            minutesRemaining = timespan.Minutes;
            if (minutesRemaining <= 0) {
                minutesRemaining = 1;
            }

            if (minutesRemaining > 1)
                displayString += minutesRemaining + " minutes ";
            else
                displayString += minutesRemaining + " minute";
        }

        countDownStart.text = displayString;

        int maxMinutesFourDaysAndChange = (4 * 24 * 60) + (20 * 60);
        int currentMinutes = (daysRemaining * 24 * 60) + (hoursRemaining * 60) + (minutesRemaining);

        countdownSlider.value = (float)(maxMinutesFourDaysAndChange - currentMinutes) / (float)maxMinutesFourDaysAndChange;
        countDownUI.SetActive(true);
    }

    IEnumerator TickingCountdown(string specialTournamentText = "", DateTime start = default(DateTime)) {
        countDownUI.SetActive(true);
        string displayString;

        // if someone leaves this tab open for over a week god bless them but I'm not responsible for their experience anymore
        // so just get the start time once
        DateTime startTime = ((start == default(DateTime)) ? GetNextWeekday(ClockInfoUTC.Date, DayOfWeek.Saturday).AddHours(hoursToAddToUTC) : start);
        int hoursRemaining;
        int minutesRemaining;
        int secondsRemaining;
        TimeSpan timespan = startTime - ClockInfoUTC;
        DateTime CountStart = DateTime.UtcNow;
        while (countDownUI && timespan.TotalSeconds > 0) {
            if (debugMode) {
                ClockInfoUTC = GetNextWeekday(DateTime.UtcNow.Date, DayOfWeek.Saturday).AddDays(addDays).AddHours(addHours + hoursToAddToUTC).AddSeconds((DateTime.UtcNow - CountStart).TotalSeconds);
            }
            else {
                ClockInfoUTC = DateTime.UtcNow;
            }

            timespan = startTime - ClockInfoUTC;
            hoursRemaining = timespan.Hours;
            minutesRemaining = timespan.Minutes;
            secondsRemaining = timespan.Seconds;
            displayString = "starts in\n" + (hoursRemaining < 10 ? "0" + hoursRemaining : hoursRemaining.ToString()) + ":" + (minutesRemaining < 10 ? "0" + minutesRemaining : minutesRemaining.ToString()) + ":" + (secondsRemaining < 10 ? "0" + secondsRemaining : secondsRemaining.ToString());
            countDownStart.text = displayString;

            int maxMinutesFourDaysAndChange = (4 * 24 * 60) + (20 * 60);
            int currentMinutes = (hoursRemaining * 60) + (minutesRemaining);

            countdownSlider.value = (float)(maxMinutesFourDaysAndChange - currentMinutes) / (float)maxMinutesFourDaysAndChange;

            yield return null;
        }
        WeekendTournamentStarted(specialTournamentText);
    }

    public static DateTime GetNextWeekday(DateTime start, DayOfWeek day) {
        // The (... + 7) % 7 ensures we end up with a value in the range [0, 6]
        int daysToAdd = ((int)day - (int)start.DayOfWeek + 7) % 7;
        return start.AddDays(daysToAdd);
    }
}
