﻿using System;
using UnityEngine;
using UnityEngine.UI;

namespace EasyCoppa
{
    public class EC_Dialog : MonoBehaviour
    {
        [SerializeField] private GameObject coppaPanel = null;
        [SerializeField] private GameObject defaultPanel = null;
        [SerializeField] private GameObject rejectionPanel = null;

        private static Dropdown dd_left;
        private static Dropdown dd_middle;
        private static Dropdown dd_right;

        public enum EC_DialogResult
        {
            EC_NOT_UNDERAGE,
            EC_UNDERAGE,
            EC_REJECTED
        }

        #region Dialog Events
        public delegate void OnCoppaDialogCompleted(EC_DialogResult result);
        public static event OnCoppaDialogCompleted onCoppaDialogCompleted;

        public delegate void OnDefaultDialogCompleted();
        public static event OnDefaultDialogCompleted onDefaultDialogCompleted;

        public delegate void OnPlayerOpenedTermsURL();
        public static event OnPlayerOpenedTermsURL onPlayerOpenedTermsURL;

        public delegate void OnPlayerOpenedPrivacyURL();
        public static event OnPlayerOpenedPrivacyURL onPlayerOpenedPrivacyURL;
        #endregion

        //To save to PlayerPrefs the player's underage status
        private static string UNDERAGE_KEY = "UNDERAGE_KEY";

        public static EC_Dialog Instance { get; private set; }

        void Awake()
        {
            if (Instance != null)
                Destroy(this);
            else
                Instance = this;
        }

        private static int daysInYear = 365;

        //Get a reference to the dropdowns set up by CanvasBuilder
        public static void SetUpDropdowns(Dropdown left, Dropdown middle, Dropdown right)
        {
            dd_left = left;
            dd_middle = middle;
            dd_right = right;
        }
        
        //Show a dialog depending on EC_Settings should show coppa
        public static void ShowDialog()
        {
            if (EC_Settings.ShouldShowCoppa())
            {
                ShowCoppaPanel();
            }
            else
            {
                ShowDefaultPanel();
            }
        }

        public static void RefreshLocalization()
        {
            if (EC_Settings.ShouldUseLocalization())
            {
                EC_CanvasBuilder.Instance.CheckLocalization();
            }
        }

        //Calculate player's age based on birth date
        private static int CalculateAge(string _day, string _month, string _year)
        {
            int userAge = 0;

            int day;
            int month;
            int year;
            
            //Convert from string to int to be able to initialize a new DateTime
            int.TryParse(_day, out day);
            int.TryParse(_month, out month);
            int.TryParse(_year, out year);

            DateTime date = new DateTime(year, month, day);

            //Get the timespan from the player's birth date to current day
            TimeSpan timeSpan = DateTime.Now - date;

            //Get the players age in years
            userAge = timeSpan.Days / daysInYear;

            return userAge;
        }

        //Show the coppa panel
        private static void ShowCoppaPanel()
        {
            Instance.coppaPanel.SetActive(true);
        }

        //Show a panel with access to the terms of service and privacy policy
        private static void ShowDefaultPanel()
        {
            Instance.defaultPanel.SetActive(true);
        }

        //Opens a browser page for the Terms of Service
        public void GUI_OpenTOSUrl()
        {
            if (onPlayerOpenedTermsURL != null)
            {
                onPlayerOpenedTermsURL();
            }

            Application.OpenURL(EC_Settings.GetTermsOfUseURL());
        }

        //Opens a browser page for the Privacy Policy
        public void GUI_OpenPrivacyURL()
        {
            if (onPlayerOpenedPrivacyURL != null)
            {
                onPlayerOpenedPrivacyURL();
            }
            
            Application.OpenURL(EC_Settings.GetPrivacyPolicyURL());
        }

        //Called when the user presses the accept button. Triggers event
        public void GUI_AcceptCoppaTerms()
        {
            string day = string.Empty;
            string month = string.Empty;
            string year = string.Empty;

            //Get the date fields to pass to the Coppa Dialog
            switch (EC_Settings.GetDateFormat())
            {
                case EC_Settings.DateFormat.DD_MM_YYYY:
                    day = dd_left.options[dd_left.value].text;
                    month = dd_middle.options[dd_middle.value].text;
                    year = dd_right.options[dd_right.value].text;
                    break;

                case EC_Settings.DateFormat.MM_DD_YYYY:
                    month = dd_left.options[dd_left.value].text;
                    day = dd_middle.options[dd_middle.value].text;
                    year = dd_right.options[dd_right.value].text;
                    break;

                case EC_Settings.DateFormat.YYYY_MM_DD:
                    year = dd_left.options[dd_left.value].text;
                    month = dd_middle.options[dd_middle.value].text;
                    day = dd_right.options[dd_right.value].text;
                    break;
            }

            //Check if the player selected valid values
            if (IsDateInputValid(day, month, year))
            {
                int age = CalculateAge(day, month, year);

                if (age < EC_Settings.UNDER_AGE && EC_Settings.ShouldRejectMinors())
                {                    
                    coppaPanel.SetActive(false);
                    rejectionPanel.SetActive(true);

                    if (onCoppaDialogCompleted != null)
                    {
                        onCoppaDialogCompleted(EC_DialogResult.EC_REJECTED);
                    }
                }
                else if (age < EC_Settings.UNDER_AGE)
                {
                    //Player is underage
                    coppaPanel.SetActive(false);
                    PlayerPrefs.SetInt(UNDERAGE_KEY, 1);
                    EC_Settings.SetPlayerUnderageFlag(true);

                    if (onCoppaDialogCompleted != null)
                    {
                        onCoppaDialogCompleted(EC_DialogResult.EC_UNDERAGE);
                    }
                }
                else
                {
                    //Player is not underage
                    coppaPanel.SetActive(false);
                    PlayerPrefs.SetInt(UNDERAGE_KEY, 0);
                    EC_Settings.SetPlayerUnderageFlag(false);

                    if (onCoppaDialogCompleted != null)
                    {
                        onCoppaDialogCompleted(EC_DialogResult.EC_NOT_UNDERAGE);
                    }
                }
            }
            else
            {
                //The player did not enter the birth date correctly. Change font to red
                SetInvalidDropdowns(day, month, year);
            }
        }

        public void GUI_AcceptDefaultTerms()
        {
            defaultPanel.SetActive(false);

            if (onDefaultDialogCompleted != null)
            {
                onDefaultDialogCompleted();
            }
        }

        public void GUI_AcceptRejection()
        {
        #if UNITY_EDITOR
            UnityEditor.EditorApplication.isPlaying = false;
        #else
            Application.Quit();
        #endif
        }

        //Did the player enter all fields correctly?
        private bool IsDateInputValid(string day, string month, string year)
        {
            bool isValid = true;

            string dayPlaceholder = "DD";
            string monthPlaceholder = "MM";
            string yearPlaceholder = "YYYY";

            if (day.CompareTo(dayPlaceholder) == 0)
            {
                //The player did not enter the day field correctly. Date is not valid
                isValid = false;
            }

            if (month.CompareTo(monthPlaceholder) == 0)
            {
                //The player did not enter the month field correctly. Date is not valid
                isValid = false;
            }

            if (year.CompareTo(yearPlaceholder) == 0)
            {
                //The player did not enter the year field correctly. Date is not valid
                isValid = false;
            }

            return isValid;
        }

        //Changes the dropdown normal color to red
        private void SetInvalidDropdownColor(Dropdown dropdown)
        {
            //Define invalid color
            float r = 1f;
            float g = 174f / 255f;
            float b = 174f / 255f;

            ColorBlock colorBlock = dropdown.colors;

            //Set invalid color
            colorBlock.normalColor = new Color(r, g, b);

            dropdown.colors = colorBlock;
        }

        //For each dropdown we check if ther value is valid and if not we change their normal color
        private void SetInvalidDropdowns(string day, string month, string year)
        {
            string dayPlaceholder = "DD";
            string monthPlaceholder = "MM";
            string yearPlaceholder = "YYYY";

            Dropdown dayDropdown = null;
            Dropdown monthDropdown = null;
            Dropdown yearDropdown = null;

            //Get dropdowns depending on date format
            switch (EC_Settings.GetDateFormat())
            {
                case EC_Settings.DateFormat.DD_MM_YYYY:
                    dayDropdown = dd_left;
                    monthDropdown = dd_middle;
                    yearDropdown = dd_right;
                    break;

                case EC_Settings.DateFormat.MM_DD_YYYY:
                    monthDropdown = dd_left;
                    dayDropdown = dd_middle;
                    yearDropdown = dd_right;
                    break;

                case EC_Settings.DateFormat.YYYY_MM_DD:
                    yearDropdown = dd_left;
                    monthDropdown = dd_middle;
                    dayDropdown = dd_right;
                    break;
            }

            //If a dropdown has an invalid value we change the normal color

            if (day.CompareTo(dayPlaceholder) == 0)
            {
                //The player did not enter the day field correctly. Date is not valid
                SetInvalidDropdownColor(dayDropdown);
            }

            if (month.CompareTo(monthPlaceholder) == 0)
            {
                //The player did not enter the month field correctly. Date is not valid
                SetInvalidDropdownColor(monthDropdown);
            }

            if (year.CompareTo(yearPlaceholder) == 0)
            {
                //The player did not enter the year field correctly. Date is not valid
                SetInvalidDropdownColor(yearDropdown);
            }
        }

        //Called when a dropdown value changes to restore the normal color
        public void OnValueChanged()
        {
            ColorBlock colorBlock = dd_left.colors;

            //Set normal color to white
            colorBlock.normalColor = Color.white;

            dd_left.colors = colorBlock;

            colorBlock = dd_middle.colors;

            //Set normal color to white
            colorBlock.normalColor = Color.white;

            dd_middle.colors = colorBlock;

            colorBlock = dd_right.colors;

            //Set normal color to white
            colorBlock.normalColor = Color.white;

            dd_right.colors = colorBlock;
        }
    }
}