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

public class Player : MonoBehaviour
{   
    public static Player Instance 
    { 
        get; private set; 
    }

    public event EventHandler<OnSelectedCounterChangedEventArgs> OnSelectedCounterChanged; 
    
    public class OnSelectedCounterChangedEventArgs : EventArgs
    {
        public ClearCounter selectedCounter; 
    }
    
    [SerializeField] private float moveSpeed = 7f;
    [SerializeField] private GameInput gameInput;
    [SerializeField] private LayerMask countersLayerMask;
    private Vector3 lastInteracDir;
    private ClearCounter selectedCounter; 

    
   private bool isWalking;  // camel case for fields 


    private void Awake()
    {
        if (Instance != null)
        {
            Debug.LogError("There has been more than one player instance !!!");
        }
        Instance = this;
    }

    private void Start()
    {
        gameInput.onInteractAction += GameInput_onInteractAction;
    }

    private void GameInput_onInteractAction(object sender, System.EventArgs e)
    {
        if (selectedCounter != null)
        {
            selectedCounter.Interact();
        }
      
    }

    private void Update()  // alwayys be explicit on showing accesor
    {

        HandleMovement();
        HandleInteraction();
    }    

    public bool IsWalking()
        {
            return isWalking;
        }

  


   
    private void HandleInteraction()
    {
        Vector2 inputVector = gameInput.GetMovementVectorNormalized();

        Vector3 moveDir = new Vector3(inputVector.x, 0f, inputVector.y);

        


        if (moveDir != Vector3.zero)
        {   
            lastInteracDir = moveDir;
        }

        float interactionDistance = 2f;

        if (Physics.Raycast(transform.position, lastInteracDir, out RaycastHit raycastHit, interactionDistance, countersLayerMask))
        {
            if (raycastHit.transform.TryGetComponent(out ClearCounter clearCounter))

            {
                // has clear counter ! 
               // clearCounter.Interact();
                if (clearCounter != selectedCounter)            
                {
                  SetSelectedCounter(selectedCounter);
                }
            }
            else
            {
               SetSelectedCounter(null);
            }
        }
        else
        {
           SetSelectedCounter(null);
        }

    }
    private void HandleMovement()
    {
        Vector2 inputVector = gameInput.GetMovementVectorNormalized();

        Vector3 moveDir = new Vector3(inputVector.x, 0f, inputVector.y);  // to mvoe our player in 2d using 3d vectors 

        float moveDistance = moveSpeed * Time.deltaTime;
        float playerRadius = 0.7f;
        float playerHeight = 2f;
        bool canMove = !Physics.CapsuleCast(transform.position, transform.position + Vector3.up * playerHeight, playerRadius, moveDir, moveDistance);


        if (!canMove)
        {
            // can not move in the moveDir 

            // Attempt only X movement 
            Vector3 moveDirX = new Vector3(moveDir.x, 0, 0).normalized;
            canMove = !Physics.CapsuleCast(transform.position, transform.position + Vector3.up * playerHeight, playerRadius, moveDirX, moveDistance);

            if (canMove)
            {
                // can move only in the X axis 
                moveDir = moveDirX;
            }
            else
            {
                // can not move only in the X axis 


                // attempt only z movememt 
                Vector3 moveDirZ = new Vector3(0, 0, moveDir.z).normalized;
                canMove = !Physics.CapsuleCast(transform.position, transform.position + Vector3.up * playerHeight, playerRadius, moveDirZ, moveDistance);
                if (canMove)
                {
                    // can move only in the Z axis 
                    moveDir = moveDirZ;

                }
                else
                {
                    // can not move in any direction 

                }
            }
        }
        if (canMove)
        {
            transform.position += moveDir * moveDistance;     // here we are adding to make our player move 
        }


        isWalking = moveDir != Vector3.zero;  // the field 
        float rotateSpeed = 10f;

        transform.forward = Vector3.Slerp(transform.forward, moveDir, Time.deltaTime * rotateSpeed);
    }

    private void SetSelectedCounter(ClearCounter selectedCounter)
    {   
        this.selectedCounter = selectedCounter;
        OnSelectedCounterChanged?.Invoke(this, new OnSelectedCounterChangedEventArgs
        {
            selectedCounter = selectedCounter
        });
    }
    }