using System;
using System.Collections;
using System.Collections.Generic;
using Unity.XR.CoreUtils;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.UI;

public class Menu : MonoBehaviour
{
    public GameObject MenuRotator;
    public GameObject Floor1Panel;
    public GameObject Floor2Panel;
    public FloorButtonVisualizer Floor1Button;
    public FloorButtonVisualizer Floor2Button;
    public Camera Camera;
    public Image PlayericonFloor1;
    public Image PlayericonFloor2;
    public GameObject PlayericonFloor1Parent;
    public GameObject PlayericonFloor2Parent;

    public XROrigin Player;
    public InputActionReference openMenuAction;
    private Canvas canvas;

    // Values for setting the position of the player marker. Do not touch them without great cause.
    private Vector2 rotatedPlayerPos = new Vector2();
    private float worldToMapAngle = 130.0f;
    private Vector2 VR_P1 = new Vector2(-77.4f, 10.1f); // - 71.2f (alumine punkt)
    private Vector2 VR_P2 = new Vector2(95.7f, -82.8f);
    private Vector2 IMG_P1 = new Vector2(-387.2f, 193.1f); // 
    private Vector2 IMG_P2 = new Vector2(389.7f, -221.4f); // 

    protected static float cameraToMapIconRotationOffset = -50;
    private float floor2UpperLimit = 9;
    private float floorsMidpointLimit = 2.5f;
    private float floor1LowerLimit = -5;
    private bool activated = true;

    private void Awake()
    {
        openMenuAction.action.Enable();
        openMenuAction.action.performed += ToggleMenu;
        InputSystem.onDeviceChange += OnDeviceChange;
        canvas = GetComponent<Canvas>();
        setCanvasVisibility(false);
        
    }
    public void DeactivateMenu() // Makes the ToggleMenu inable to toggle.
    {
        canvas.enabled = false;
        activated = false;
    }
    public void ReactivateMenu() // Makes the ToggleMenu able to toggle again.
    {
        activated = true;
    }

    public void setCanvasVisibility(bool enabled)
    {
        canvas.enabled = enabled;
    }

    private void ToggleMenu(InputAction.CallbackContext context)
    {
        if (!activated) return;
        
        updateMenuTransform();

        // Toggle the menu visibility
        setCanvasVisibility(!canvas.enabled);
    }

    public Transform updateMenuTransform()
    {
        // Gets the transform of the menu Updates the transform along the way
        // Does not enable its visibility.


        // Get the camera's local Y rotation relative to the parent of MenuRotator
        float relativeYRotation = Camera.transform.localEulerAngles.y;
        // Apply the relative Y rotation to MenuRotator while keeping X and Z unchanged
        MenuRotator.transform.localEulerAngles = new Vector3(0, relativeYRotation, 0);

        // Set the menu position to match the camera's position in local space
        MenuRotator.transform.position = Camera.transform.position;     

        return this.transform;

    }

    // Start is called before the first frame update
    void Start()
    {
        Floor1Button.GetComponent<Button>().onClick.AddListener(DisplayFloor1);
        Floor2Button.GetComponent<Button>().onClick.AddListener(DisplayFloor2);
        DisplayFloor2();
    }
    private void DisplayFloor1()
    {
        //Debug.Log("Dispaling floor 1");
        Floor1Panel.gameObject.SetActive(true);
        Floor2Panel.gameObject.SetActive(false);

        Button buttonComponent = Floor1Button.GetComponent<Button>();

        // Refresh the state of the button.
        buttonComponent.interactable = false;
        buttonComponent.interactable = true;
    }
    private void DisplayFloor2()
    {
        //Debug.Log("Dispaling floor 2");
        Floor1Panel.gameObject.SetActive(false);
        Floor2Panel.gameObject.SetActive(true);

        Button buttonComponent = Floor2Button.GetComponent<Button>();

        // Refresh the state of the button.
        buttonComponent.interactable = false;
        buttonComponent.interactable = true;
    }
    private int DeterminePlayerCurrentFloor()
    {
        float yPos = gameObject.transform.position.y;
        if (yPos > floorsMidpointLimit && yPos < floor2UpperLimit) // Floor 2
        {
            return 2;
        }
        if (yPos > floor1LowerLimit && yPos <= floorsMidpointLimit) // Floor 1
        {
            return 1;
        }
        return -1; // If the player should not be on the map
    }

    private void OnDeviceChange(InputDevice device, InputDeviceChange change) // To avoid bugs with controllers disconnecting.
    {
        switch (change)
        {
            case InputDeviceChange.Disconnected:
                openMenuAction.action.Disable();
                openMenuAction.action.performed -= ToggleMenu;
                break;
            case InputDeviceChange.Reconnected:
                openMenuAction.action.Enable();
                openMenuAction.action.performed += ToggleMenu;
                break;
        }
    }
    
    // Update is called once per frame
    void Update()
    {
        if (transform.position.y < -50) // If the player has fallen off the platform.
        {
            if (!canvas.enabled) // If has menu not activated.
            {
                ToggleMenu(new InputAction.CallbackContext()); // Activate menu.
            }
        }
        
        UpdatePlayerIconPosition();
        UpdatePlayerIconRotation();
        UpdateActveFloor();



    }
    private void UpdatePlayerIconRotation()
    {
        float cameraRotationY = -Camera.transform.eulerAngles.y;
        float iconRotation = cameraRotationY + cameraToMapIconRotationOffset;
        if (PlayericonFloor1Parent.activeSelf)
        {
            PlayericonFloor1.transform.rotation = Quaternion.Euler(transform.eulerAngles.x, transform.eulerAngles.y, iconRotation);
        }
        if (PlayericonFloor2Parent.activeSelf)
        {
            PlayericonFloor2.transform.rotation = Quaternion.Euler(transform.eulerAngles.x, transform.eulerAngles.y, iconRotation);
        }
    }
    private void UpdateActveFloor()
    {
        int playerCurrentFloor = DeterminePlayerCurrentFloor();
        //Debug.Log("Player current floor is " + playerCurrentFloor);
        switch (playerCurrentFloor)
        {
            case 1:
                if (!Floor1Button.ActiveState)
                {
                    //Debug.Log("Activating floor 1 Button.");
                    Floor1Button.Activate();
                    Floor2Button.Deactivate();
                }
                if (!PlayericonFloor1Parent.activeSelf)
                {
                    PlayericonFloor1Parent.SetActive(true);
                    PlayericonFloor2Parent.SetActive(false);
                }
                break;
            case 2:
                if (!Floor2Button.ActiveState)
                {
                    //Debug.Log("Activating floor 2 Button.");
                    Floor1Button.Deactivate();
                    Floor2Button.Activate();
                }
                if (!PlayericonFloor2Parent.activeSelf)
                {
                    Debug.Log("PlayericonFloor2Parent is inactive");
                    PlayericonFloor1Parent.SetActive(false);
                    PlayericonFloor2Parent.SetActive(true);
                    Debug.Log(PlayericonFloor2Parent.activeSelf);
                }
                break;
            default:
                if (PlayericonFloor1Parent.activeSelf || PlayericonFloor2Parent.activeSelf) 
                {
                    //Debug.Log("Deactivating floor Buttons.");
                    Floor1Button.Deactivate();
                    Floor2Button.Deactivate();
                }
                if (PlayericonFloor1.enabled || PlayericonFloor2.enabled)
                {
                    PlayericonFloor1Parent.SetActive(false);
                    PlayericonFloor2Parent.SetActive(false);
                }
                break;

        }

    }


    private void UpdatePlayerIconPosition()
    {
        float worldToMapAngleRad = worldToMapAngle * Mathf.Deg2Rad;

        //Vector2 VR_Player = new Vector2(transform.position.x, transform.position.z);
        Vector2 VR_Player = new Vector2(
            Mathf.Cos(worldToMapAngleRad) * transform.position.x - Mathf.Sin(worldToMapAngleRad) * transform.position.z,
            Mathf.Sin(worldToMapAngleRad) * transform.position.x + Mathf.Cos(worldToMapAngleRad) * transform.position.z
        );

        VR_Player = VR_Player * new Vector2(1.0f, 1.0f);

        rotatedPlayerPos = VR_Player;
        //Debug.Log(VR_Player);

        //Vector2 VR_P1 = new Vector2(-10, 102);
        //Vector2 VR_P2 = new Vector2(-123, -19);

        /*Vector2 VR_P1 = new Vector2(-102.0f, 73.0f);
        Vector2 VR_P2 = new Vector2(71.1f, 76.6f);
        

        Vector2 IMG_P1 = new Vector2(-364.0f, -180.0f);
        Vector2 IMG_P2 = new Vector2(394.0f, -225.0f);*/

        Vector2 VR_L = VR_P2 - VR_P1;
        Vector2 IMG_L = IMG_P2 - IMG_P1;

        Vector2 IMG_Player = (VR_Player - VR_P1) / VR_L * IMG_L + IMG_P1;
        if (PlayericonFloor1Parent.activeSelf)
        {
            PlayericonFloor1.GetComponent<RectTransform>().anchoredPosition = IMG_Player;
        }
        if (PlayericonFloor2Parent.activeSelf)
        {
            PlayericonFloor2.GetComponent<RectTransform>().anchoredPosition = IMG_Player;
        }

        /*
        float VR_X = transform.position.x;
        float VR_Y = transform.position.y;

        float VR_X1 = -10;
        float VR_X2 = -123;
        float IMG_X1 = -364;
        float IMG_X2 = 394;


        float Lvr = VR_X2 - VR_X1;//(-138 - -10)
        float Limg = IMG_X2 - IMG_X1;

        IMG_X = (VR_X - VR_X1) / Lvr * Limg + IMG_X1;
        */
        //IMG_Y = (VR_Y - VR_Y1) / Lvr * Limg + IMG_Y1;
        //Playericon.transform.position.Set(IMG_X,0,0);
        //Playericon.GetComponent<RectTransform>().anchoredPosition = new Vector2(IMG_X, IMG_Y);
        //Debug.Log(IMG_X + " vs " + Playericon.GetComponent<RectTransform>().anchoredPosition.x);
    }
    private void OnDestroy()
    {
        openMenuAction.action.Disable();
        openMenuAction.action.performed -= ToggleMenu;
        InputSystem.onDeviceChange -= OnDeviceChange;
        Floor1Button.GetComponent<Button>().onClick.RemoveListener(DisplayFloor1);
        Floor2Button.GetComponent<Button>().onClick.RemoveListener(DisplayFloor2);
    }
}