using System.Collections.Generic;
using System.Text.RegularExpressions;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

/// <summary>
/// UserCreationScreen scene manager
/// </summary>
public class UserCreationScreen : MonoBehaviour
{
    /// <summary>
    /// Maximum lenght of a username
    /// </summary>
    private const int MAX_USERNAME_LENGTH = 12;

    /// <summary>
    /// Reference to the input text field for username
    /// </summary>
    public TMP_InputField inputName;

    /// <summary>
    /// Reference to the avatar-list container
    /// </summary>
    public Transform avatarsContainer;

    /// <summary>
    /// Avatar prefab
    /// </summary>
    public GameObject avatarPrefab;

    /// <summary>
    /// List of all sprites that are supported as avatars
    /// </summary>
    public List<Sprite> sprites = new List<Sprite>();

    /// <summary>
    /// Reference to the UserList ScriptableObject
    /// </summary>
    public UserList users;

    /// <summary>
    /// Current selected avatar
    /// </summary>
    [SerializeField]
    private int selectedAvatar = 0;

    /// <summary>
    /// List of references to avatar background sprites (so we can color them nicely)
    /// </summary>
    private List<Image> avatars = new List<Image>();


    /// <summary>
    /// Start is called before the first frame update
    /// </summary>
    void Start()
    {
        for (int i = 0; i < sprites.Count; i++)
        {
            // Create instance of prefab
            GameObject instance = GameObject.Instantiate(avatarPrefab, avatarsContainer);

            // Store value of i so we can use it the callback (else it would get the value of sprites.Count)
            int x = i;
            // Add onClick callback
            instance.GetComponent<Button>().onClick.AddListener(() => UpdateAvatar(x));

            // Store reference to image for fancy coloring
            Image background = instance.GetComponent<Image>();
            avatars.Add(background);
            // Set background color
            background.color = selectedAvatar == i ? Color.blue : Color.gray;
            // Find correct component for setting the sprite
            foreach (Image img in background.GetComponentsInChildren<Image>())
                if (img != background)
                {
                    img.sprite = sprites[i];
                    break;
                }
        }
    }

    /// <summary>
    /// Update the current selected avatar
    /// </summary>
    /// <param name="newAvatar">Index to the new avatar in the <c>this.avatars</c> list</param>
    private void UpdateAvatar(int newAvatar)
    {
        avatars[selectedAvatar].color = Color.gray;
        selectedAvatar = newAvatar;
        avatars[selectedAvatar].color = Color.blue;
    }

    /// <summary>
    /// Check if a given string is a correct username (using Regex)
    /// </summary>
    /// <param name="username">The username to be checked</param>
    /// <returns><c>true</c> if the username was valid, <c>false</c> otherwise</returns>
    static public bool IsValidUsername(string username)
    {
        return new Regex($@"^[abcdefghijklmnopqrstuvwxyz]{{1,{MAX_USERNAME_LENGTH}}}$").IsMatch(username);
    }

    /// <summary>
    /// Create a new user
    /// (this method will be called by a button callback)
    /// </summary>
    public void CreateUser()
    {
        string username = inputName.text;
        if (IsValidUsername(username))
        {
            if (users.GetUserByUsername(username) == null)
            {
                // Create a new entry in the UserList ScriptableObject
                users.CreateAndAddNewUser(username, sprites[selectedAvatar]);
                // TODO: change scene, for now just change to StartScreen
                SceneManager.LoadScene("Common/Scenes/StartScreen");
            }
            // TODO: give more feedback to user
            // Warn user that username already exists
            else Debug.LogWarning($"Username '{username}' already exists!");
        }
        // TODO: give more feedback to user
        // Warn user that username is invalid
        else Debug.LogWarning($"Invalid username '{username}'!");
    }
}
