using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;
using System.Security.Cryptography;
using System.Text;
using System;

public class Register : MonoBehaviour {
    public GameObject username;
    public GameObject password;
    public GameObject email;
    public Text errorText;

    public Button registerButton;

    private string Username;
    private string Password;
    private string Email;
    private string form;
    Firebase.Auth.FirebaseAuth auth;
    string salt;

    private string registerUserUrl = "http://nordh.xyz/narKampen/dbFiles/Register.php?";

    private Color errorColor;

    private EventSystem system;

    // Start is called before the first frame update
    void Start() {
        // CheckFirebaseGoogleDependencies();
        registerButton.onClick.AddListener(RegisterAction);
        system = EventSystem.current;
        errorColor = errorText.color;
        auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
    }

    // Update is called once per frame
    void Update() {
        Username = username.GetComponent<InputField>().text;
        Password = password.GetComponent<InputField>().text;
        Email = email.GetComponent<InputField>().text;

        if (Input.GetKeyDown(KeyCode.Tab)) {
            Selectable next = system.currentSelectedGameObject.GetComponent<Selectable>().FindSelectableOnDown();

            if (next != null) {

                InputField inputfield = next.GetComponent<InputField>();
                if (inputfield != null) inputfield.OnPointerClick(new PointerEventData(system));  //if it's an input field, also set the text caret

                system.SetSelectedGameObject(next.gameObject, new BaseEventData(system));
            }
        }
    }

    void RegisterAction() {
        string errorMessage = "";
        if (Username == "" || Username.Length < 3) {
            errorMessage = LocalizationManager.Instance.GetText("REGISTER_ERROR_USERNAME_EMPTY");
        }
        if (Password == "") {
            if (errorMessage != "") {
                errorMessage += "\n";
            }
            errorMessage += LocalizationManager.Instance.GetText("REGISTER_ERROR_PASSWORD_EMPTY");
        }
        if (Password.Length < 6) {
            if (errorMessage != "") {
                errorMessage += "\n";
            }
            errorMessage += LocalizationManager.Instance.GetText("REGISTER_ERROR_PASSWORD_TO_SHORT");
        }
        if (Email == "") {
            if (errorMessage != "") {
                errorMessage += "\n";
            }
            errorMessage += LocalizationManager.Instance.GetText("REGISTER_ERROR_EMAIL_EMPTY");
        }


        if (errorMessage != "") {
            errorText.text = errorMessage;
            errorColor.a = 1;
        } else {
            errorColor.a = 0;
            FirebaseRegister(Email, Password);
            StartCoroutine(RegisterUser());
        }
        errorText.color = errorColor;
    }

    private void FirebaseRegister(String email, String password) {
        auth.CreateUserWithEmailAndPasswordAsync(email, password).ContinueWith(task => {
            if (task.IsCanceled) {
                Debug.LogError("CreateUserWithEmailAndPasswordAsync was canceled.");
                return;
            }
            if (task.IsFaulted) {
                Debug.LogError("CreateUserWithEmailAndPasswordAsync encountered an error: " + task.Exception);
                return;
            }

            // Firebase user has been created.
            Firebase.Auth.FirebaseUser newUser = task.Result;
            Debug.LogFormat("Firebase user created successfully: {0} ({1})",
                newUser.DisplayName, newUser.UserId);
        });
    }

    IEnumerator RegisterUser() {
        // TODO register user at server, check for already in use for username and email.

        // TODO - Save OS and device id
        string deviceId = SystemInfo.deviceUniqueIdentifier;
        string os = SystemInfo.operatingSystem;

        string salt = GetSalt();
        string password = getPassword();

        string postUrl = registerUserUrl + "name=" + UnityWebRequest.EscapeURL(Username) + "&password=" + UnityWebRequest.EscapeURL(password) + "&email=" + UnityWebRequest.EscapeURL(Email) + "&s=" + UnityWebRequest.EscapeURL(salt) + "&did=" + deviceId + "&os=" + UnityWebRequest.EscapeURL(os);
        UnityWebRequest www = UnityWebRequest.Get(postUrl);
        yield return www.SendWebRequest();

        if (www.error != null) {
            errorText.text = LocalizationManager.Instance.GetText("REGISTER_ERROR_CONNECTION_FAIL");
            errorColor.a = 1;
            errorText.color = errorColor;
        } else {

            string result = www.downloadHandler.text;
            if (int.TryParse(www.downloadHandler.text, out int userId)) {
                errorColor.a = 0;
                errorText.color = errorColor;
                Database.Instance.KeepSignedIn(Username, userId, false);
                SceneManager.LoadScene("MainMenu");
            } else {
                errorText.text = LocalizationManager.Instance.GetText("REGISTER_ERROR_USER_PASS_ALREADY_IN_USE");
                errorColor.a = 1;
                errorText.color = errorColor;
            }
        }
    }

    private string getPassword() {

        byte[] pass;
        salt = GetSalt();
        byte[] pwd = Encoding.UTF8.GetBytes(salt + Password);
        SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
        pass = sha1.ComputeHash(pwd);

        return Convert.ToBase64String(pass);
    }

    private string GetSalt() {
        if (this.salt == null) {
            RNGCryptoServiceProvider rnd = new RNGCryptoServiceProvider();

            int saltLength = 32;
            byte[] slt = new byte[saltLength];

            rnd.GetNonZeroBytes(slt);
            this.salt = Convert.ToBase64String(slt);
        }
        return this.salt;
    }

    private void CheckFirebaseGoogleDependencies() {
        Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => {
            var dependencyStatus = task.Result;
            if (dependencyStatus == Firebase.DependencyStatus.Available) {
                // Create and hold a reference to your FirebaseApp,
                // where app is a Firebase.FirebaseApp property of your application class.
                //   app = Firebase.FirebaseApp.DefaultInstance;

                // Set a flag here to indicate whether Firebase is ready to use by your app.
            } else {
                UnityEngine.Debug.LogError(System.String.Format(
                  "Could not resolve all Firebase dependencies: {0}", dependencyStatus));
                // Firebase Unity SDK is not safe to use here.
            }
        });
    }
}
