using System.Collections;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

namespace DesktopVision {
public class KeyboardEventArgs : EventArgs
{
    public string eventName {get; set;}
    public key key { get; set; }
    public Boolean shift { get; set; }
    public Boolean alt { get; set; }
    public Boolean ctrl { get; set; }
}
public class DVKeyboard : MonoBehaviour
{
    /// <summary>
    /// The panel used for the letters keyboard layout
    /// </summary>
    [SerializeField] Transform letters;
    /// <summary>
    /// The panel used for the numbers keyboard layout
    /// </summary>
    [SerializeField] Transform numbers;
    /// <summary>
    /// The panel used for the symbols keyboard layout
    /// </summary>
    [SerializeField] Transform symbols;
    /// <summary>
    /// The keyboard layout to create keys with
    /// </summary>
    private KeyboardLayout layout;
    /// <summary>
    /// The button prefab used to create keys
    /// </summary>
    public GameObject buttonFab;
    /// <summary>
    /// If the keyboard is in the shift state
    /// </summary>
    public Transform currentPannel;
    /// <summary>
    /// If the keyboard is in the shift state
    /// </summary>
    public bool shifting = false;
    /// <summary>
    /// If the keyboard should track the camera
    /// </summary>

    public bool followsCamera = false;
    
    /// <summary>
    /// If the keyboard is in the shift state
    /// </summary>
    public event EventHandler<KeyboardEventArgs> Dispatch;
    private List<Button> buttons;

    private void Start()
    {
        layout = new KeyboardLayout();
        CreateKeyboardLayout(layout.letterLayout, letters);
        CreateKeyboardLayout(layout.numberLayout, numbers);
        CreateKeyboardLayout(layout.symbolLayout, symbols);

        toggleKeyboardState(letters);
    }

    void LateUpdate()
    {
    }

    protected virtual void DispatchEvent(KeyboardEventArgs e)
    {
        e.shift = shifting;
        EventHandler<KeyboardEventArgs> handler = Dispatch;
        Dispatch.Invoke(this, e);
    }
    private void CreateKeyboardLayout(List<List<key>> layout, Transform panel)
    {
        int rowIdx = 0;
        int gap = 10;
        foreach (List<key> row in layout)
        {
            int keyboardHeight = 1000;
            int keyboardWidth = 2000;
            float remainingWidth = 100;
            float keys = row.Count;

            foreach (key key in row)
            {
                remainingWidth -= key.width;
                if (key.width > 0) keys -= 1;
            }

            float baseKeyWidth = remainingWidth / keys;
            float xOffset = -keyboardWidth / 2 + gap;
            float yOffset = keyboardHeight / 2 - gap;
            foreach (key key in row)
            {
                float keyWidthPercentage = baseKeyWidth / 100f;
                if (key.width > 0) keyWidthPercentage = key.width / 100f;

                float keyWidth = keyWidthPercentage * (keyboardWidth - gap * (row.Count + 2));
                float keyHeight = (keyboardHeight - (layout.Count + 2) * gap) / layout.Count;
                float y = yOffset - (keyHeight / 2) - (keyHeight * rowIdx) - (gap * rowIdx);
                float x = xOffset + (keyWidth / 2);

                Vector3 position = new Vector3(x, y, 0);
                Vector2 size = new Vector2(keyWidth, keyHeight);
                UnityEngine.Events.UnityAction keyEvent = () => handleKeyboardButton(key);

                CreateButton(position, size, keyEvent, key, panel);
                xOffset += keyWidth + gap;
            }
            rowIdx += 1;
        }
    }

    private void CreateButton(Vector3 position, Vector2 size, UnityEngine.Events.UnityAction method, key key, Transform panel)
    {
        GameObject button = Instantiate(buttonFab, position, Quaternion.identity);

        button.transform.SetParent(panel);
        button.transform.localScale = new Vector3(1, 1, 1);
        button.transform.localRotation = Quaternion.identity;

        button.GetComponent<RectTransform>().anchoredPosition3D = position;
        button.GetComponent<RectTransform>().sizeDelta = size;
        button.GetComponent<Button>().onClick.AddListener(method);

        Text buttonLabel = button.GetComponentInChildren<Text>();
        buttonLabel.text = key.label;
        key.buttonLabel = buttonLabel;
    }

    private void handleKeyboardButton(key key)
    {
        if (key.id == "toggleNumbers")
        {
            toggleKeyboardState(numbers);
        }
        else if (key.id == "toggleLetters")
        {
            toggleKeyboardState(letters);
        }
        else if (key.id == "toggleSymbols")
        {
            toggleKeyboardState(symbols);
        }
        else if (key.id == "shift")
        {
            shiftLetters();
        }
        else
        {
            KeyboardEventArgs args = new KeyboardEventArgs();
            args.key = key;
            DispatchEvent(args);
        }
    }

    private void shiftLetters()
    {
        foreach (List<key> row in layout.letterLayout)
        {
            foreach (key key in row)
            {
                if (shifting)
                    key.buttonLabel.text = key.label;
                else
                    key.buttonLabel.text = key.shiftLabel;
            }
        }
        shifting = !shifting;
    }

    private void toggleKeyboardState(Transform active)
    {
        letters.gameObject.SetActive(false);
        symbols.gameObject.SetActive(false);
        numbers.gameObject.SetActive(false);

        active.gameObject.SetActive(true);
        currentPannel = active;
    }
}
}