﻿using AsmodeeDigital.AccountManagement.Plugin.Manager;
using AsmodeeDigital.AccountManagement.Samples.UI;
using AsmodeeDigital.Common.Plugin.Domain.Players;
using AsmodeeDigital.Common.Plugin.Manager.Scene;
using AsmodeeDigital.Common.Plugin.Network;
using AsmodeeDigital.Common.Samples.UI;
using System;
using System.Text.RegularExpressions;
using UnityEngine;

namespace AsmodeeDigital.AccountManagement.Samples.Views
{
    public class AccountManagementView : MonoBehaviour
    {
        [Serializable]
        public class UI
        {
            public Popup DoYouHaveAnAccountPopup;
            public PopupInputField LoginPopup;
            public PopupInputField EnterPasswordPopup;
            public PopupChooseALogin ChooseALoginNamePopup;
            public PopupWelcome WelcomePopup;
            public Popup PopupMessage;
        }

        private enum State
        {
            DoYouHaveAnAccount,
            SearchLoginOrEmail,
            EnterPassword,
            Logged,
            AccountCreation,
            ChooseLoginName,
        }

        [HideInInspector]
        public AccountManagementView Instance;

        public UI ui;

        private RestAPI _restAPI;
        private User _user = null;
        private State _state = State.DoYouHaveAnAccount;

        private void OnEnable()
        {
            Instance = this;
        }

        private void Start()
        {
            Init();
        }

        private void Init()
        {
            _restAPI = AccountManager.Instance.RestAPI;

            _restAPI.AccountCreatedEvent += _restAPI_AccountCreatedEvent;
            _restAPI.AccountCreationErrorEvent += _restAPI_AccountCreationErrorEvent;
            _restAPI.AuthenticationErrorEvent += _restAPI_AuthenticationErrorEvent;
            _restAPI.AuthenticationSuccessEvent += _restAPI_AuthenticationSuccessEvent;
            _restAPI.ConnectionSuccessEvent += _restAPI_ConnectionSuccessEvent;
            _restAPI.EmailFoundEvent += _restAPI_EmailFoundEvent;
            _restAPI.EmailNotFoundEvent += _restAPI_EmailNotFoundEvent;
            _restAPI.LoginFoundEvent += _restAPI_LoginFoundEvent;
            _restAPI.LoginNotFoundEvent += _restAPI_LoginNotFoundEvent;
            _restAPI.LostPasswordEmailSentEvent += _restAPI_LostPasswordEmailSentEvent;
            _restAPI.LostPasswordErrorEvent += _restAPI_LostPasswordErrorEvent;

            _restAPI.Connect();
        }

        public void ShowMainMenu()
        {
            SceneManager.LoadScene("1_MainMenu");
        }

        #region DoYouHaveAnAccount
        public void DoYouHaveAnAccount_No()
        {
            _state = State.AccountCreation;

            ui.DoYouHaveAnAccountPopup.Hide();
            ui.WelcomePopup.Show();
        }

        public void DoYouHaveAnAccount_Yes()
        {
            _state = State.SearchLoginOrEmail;

            ui.DoYouHaveAnAccountPopup.Hide();
            ui.LoginPopup.Show();
        }
        #endregion

        #region Login
        public void Login_Cancel()
        {
            _state = State.DoYouHaveAnAccount;

            ui.LoginPopup.Hide();
            ui.DoYouHaveAnAccountPopup.Show();
        }

        public void Login_Ok()
        {
            string loginOrEmail = ui.LoginPopup.uiPopupInputField.InputField.text;
            bool isEmail = Regex.IsMatch(loginOrEmail, @"\A(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\Z", RegexOptions.IgnoreCase);

            if (isEmail)
            {
                _restAPI.SearchByEmail(loginOrEmail);
            }
            else
            {
                _restAPI.SearchByLogin(loginOrEmail, false);
            }
        }

        private void LoginOrMailFound(User user)
        {
            _state = State.EnterPassword;

            _user = user;

            ui.LoginPopup.Hide();
            ui.EnterPasswordPopup.Show();
        }

        private void LoginOrMailNotFound()
        {
            ui.LoginPopup.uiPopupInputField.ErrorMessage.gameObject.SetActive(true);

            ui.LoginPopup.SelectInputFieldContent();
        }

        public void Login_OnInputChange(string value)
        {
            ui.LoginPopup.uiPopupInputField.ErrorMessage.gameObject.SetActive(false);
        }
        #endregion

        #region EnterPassword
        public void EnterPassword_ResetPassword()
        {
            _restAPI.ResetPassword(_user.DoWID);
        }

        public void EnterPassword_Cancel()
        {
            _state = State.SearchLoginOrEmail;

            _user = null;

            ui.EnterPasswordPopup.Hide();
            ui.LoginPopup.Show();
        }

        public void EnterPassword_Ok()
        {
            string password = ui.EnterPasswordPopup.uiPopupInputField.InputField.text;

            _restAPI.Authentication(_user.Login, password);
        }

        public void EnterPassword_OnInputChange(string value)
        {
            ui.EnterPasswordPopup.uiPopupInputField.ErrorMessage.gameObject.SetActive(false);
        }
        #endregion

        #region Welcome
        public void Welcome_Cancel()
        {
            _state = State.DoYouHaveAnAccount;

            _user = null;

            ui.WelcomePopup.Hide();
            ui.DoYouHaveAnAccountPopup.Show();
        }

        public void Welcome_SignUP()
        {
            string email = ui.WelcomePopup.uiPopupWelcome.Email.text;
            bool isEmail = Regex.IsMatch(email, @"\A(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\Z", RegexOptions.IgnoreCase);

            string password = ui.WelcomePopup.uiPopupWelcome.Password.text;

            if (!isEmail)
            {
                ui.WelcomePopup.uiPopupWelcome.ErrorMessage.text = "The e-mail is invalid";
                ui.WelcomePopup.uiPopupWelcome.ErrorMessage.gameObject.SetActive(true);

                return;
            }

            if (password.Length < 6)
            {
                ui.WelcomePopup.uiPopupWelcome.ErrorMessage.text = "Password is too short";
                ui.WelcomePopup.uiPopupWelcome.ErrorMessage.gameObject.SetActive(true);

                return;
            }

            _restAPI.SearchByEmail(email);
        }

        private void WelcomeEmailFound(User user)
        {
            _state = State.EnterPassword;

            _user = user;

            ui.WelcomePopup.Hide();
            ui.LoginPopup.uiPopupInputField.InputField.text = ui.WelcomePopup.uiPopupWelcome.Email.text;
            ui.EnterPasswordPopup.Show();
        }

        private void WelcomeContinueAccountCreation()
        {
            _state = State.ChooseLoginName;

            ui.WelcomePopup.Hide();
            ui.ChooseALoginNamePopup.Show();
        }
        #endregion

        #region ChosseALogin
        public void ChooseALogin_Skip()
        {
            _restAPI.CreateAccount(
                string.Empty,
                ui.WelcomePopup.uiPopupWelcome.Password.text,
                ui.WelcomePopup.uiPopupWelcome.Email.text,
                ui.WelcomePopup.uiPopupWelcome.SubscribeNewsletter.isOn);
        }

        public void ChooseALogin_OK()
        {
            _restAPI.CreateAccount(
                ui.ChooseALoginNamePopup.uiPopupChooseALogin.Login.text, 
                ui.WelcomePopup.uiPopupWelcome.Password.text, 
                ui.WelcomePopup.uiPopupWelcome.Email.text, 
                ui.WelcomePopup.uiPopupWelcome.SubscribeNewsletter.isOn);
        }

        public void ChooseALogin_OnInputChange(string value)
        {
            _restAPI.SearchByLogin(ui.ChooseALoginNamePopup.uiPopupChooseALogin.Login.text, false);
        }

        private void LoginFound(User user)
        {
            ui.ChooseALoginNamePopup.uiPopupChooseALogin.LoginFound.gameObject.SetActive(true);
            ui.ChooseALoginNamePopup.uiPopupChooseALogin.LoginNotFound.gameObject.SetActive(false);

            ui.ChooseALoginNamePopup.ui.Buttons[1].interactable = false;
        }

        private void LoginNotFound()
        {
            ui.ChooseALoginNamePopup.uiPopupChooseALogin.LoginFound.gameObject.SetActive(false);
            ui.ChooseALoginNamePopup.uiPopupChooseALogin.LoginNotFound.gameObject.SetActive(true);

            ui.ChooseALoginNamePopup.ui.Buttons[1].interactable = true;
        }
        #endregion

        #region REST API Events
        private void _restAPI_ConnectionSuccessEvent()
        {
            ui.DoYouHaveAnAccountPopup.Show();
        }

        private void _restAPI_LoginFoundEvent(User user)
        {
            if (_state == State.SearchLoginOrEmail)
                LoginOrMailFound(user);
            else if (_state == State.ChooseLoginName)
                LoginFound(user);
        }

        private void _restAPI_LoginNotFoundEvent()
        {
            if (_state == State.SearchLoginOrEmail)
                LoginOrMailNotFound();
            else if (_state == State.ChooseLoginName)
                LoginNotFound();
        }

        private void _restAPI_EmailFoundEvent(User user)
        {
            if (_state == State.SearchLoginOrEmail)
                LoginOrMailFound(user);
            else if (_state == State.AccountCreation)
                WelcomeEmailFound(user);
        }

        private void _restAPI_EmailNotFoundEvent()
        {
            if (_state == State.SearchLoginOrEmail)
                LoginOrMailNotFound();
            else if (_state == State.AccountCreation)
                WelcomeContinueAccountCreation();
        }

        private void _restAPI_AuthenticationSuccessEvent(string refreshToken)
        {
            ui.EnterPasswordPopup.Hide();
            ui.PopupMessage.Show("LOGGED IN", "You are successfully logged in");
        }

        private void _restAPI_AuthenticationErrorEvent(string error)
        {
            ui.EnterPasswordPopup.uiPopupInputField.ErrorMessage.text = error;
            ui.EnterPasswordPopup.uiPopupInputField.ErrorMessage.gameObject.SetActive(true);

            ui.EnterPasswordPopup.SelectInputFieldContent();
        }

        private void _restAPI_AccountCreatedEvent(User user)
        {
            ui.ChooseALoginNamePopup.Hide();
            ui.PopupMessage.Show("ACCOUNT CREATED", "Thank you.\r\nA confirmation e-mail was sent to you");
        }

        private void _restAPI_AccountCreationErrorEvent(string error)
        {
            ui.ChooseALoginNamePopup.uiPopupChooseALogin.ErrorMessage.text = error;
            ui.ChooseALoginNamePopup.uiPopupChooseALogin.ErrorMessage.gameObject.SetActive(true);
        }

        private void _restAPI_LostPasswordEmailSentEvent()
        {
            ui.ChooseALoginNamePopup.Hide();
            ui.PopupMessage.Show("RESET PASSWORD", "We sent you an e-mail. Please follow the instructions to retrieve your password", ()=>
            {
                _state = State.EnterPassword;
                ui.EnterPasswordPopup.Show();
            });
        }

        private void _restAPI_LostPasswordErrorEvent(string error)
        {
            ui.EnterPasswordPopup.uiPopupInputField.ErrorMessage.text = error;
            ui.EnterPasswordPopup.uiPopupInputField.ErrorMessage.gameObject.SetActive(true);

            ui.EnterPasswordPopup.SelectInputFieldContent();
        }
        #endregion

        private void Dispose()
        {
            _restAPI.AccountCreatedEvent -= _restAPI_AccountCreatedEvent;
            _restAPI.AccountCreationErrorEvent -= _restAPI_AccountCreationErrorEvent;
            _restAPI.AuthenticationErrorEvent -= _restAPI_AuthenticationErrorEvent;
            _restAPI.AuthenticationSuccessEvent -= _restAPI_AuthenticationSuccessEvent;
            _restAPI.ConnectionSuccessEvent -= _restAPI_ConnectionSuccessEvent;
            _restAPI.EmailFoundEvent -= _restAPI_EmailFoundEvent;
            _restAPI.EmailNotFoundEvent -= _restAPI_EmailNotFoundEvent;
            _restAPI.LoginFoundEvent -= _restAPI_LoginFoundEvent;
            _restAPI.LoginNotFoundEvent -= _restAPI_LoginNotFoundEvent;
        }
    }
}
