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

public class PlayerController : MonoBehaviour
{

    public float walkingSpeed = 7.5f;
    public float runningSpeed = 11.5f;
    public float jumpSpeed = 8.0f;
    public float gravity = 20.0f;
    public Camera playerCamera;
    public float lookSpeed = 2.0f;
    public float lookXLimit = 45.0f;

    public GameObject Level;
    public GameObject InventoryInterface;
    public GameObject MonolithInterface;
    public GameObject BuildingInterface;
    public GameObject QuestInterface;
    public GameObject InventoryButtonInterface;
    public GameObject InventoryButtonInterfaceResource;

    CharacterController characterController;
    Vector3 moveDirection = Vector3.zero;
    float rotationX = 0;


    [HideInInspector]
    public bool canMove = true;

    void Start()
    {
        characterController = GetComponent<CharacterController>();
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }

    void Update()
    {
        // recalculate move direction
        Vector3 forward = transform.TransformDirection(Vector3.forward);
        Vector3 right = transform.TransformDirection(Vector3.right);

        // raycast
        var isOnWall = false;
        if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out RaycastHit hit))
        {
            if (hit.distance <= 1f)
            {
                var tile = hit.transform.parent;
                if (tile.transform.tag == "Tile")
                {
                    if (hit.normal.magnitude == 1f && hit.normal.y == 0)
                        isOnWall = true;
                }
            }
        }

        // swimming
        var isSwimming = false;
        if (Camera.main.transform.position.y < 0f)
        {
            isSwimming = true;
        }

        // run
        bool isRunning = Input.GetKey(KeyCode.LeftShift);
        float curSpeedX = canMove ? (isRunning ? runningSpeed : walkingSpeed) * Input.GetAxis("Vertical") : 0;
        float curSpeedY = canMove ? (isRunning ? runningSpeed : walkingSpeed) * Input.GetAxis("Horizontal") : 0;
        float movementDirectionY = moveDirection.y;
        moveDirection = (forward * curSpeedX) + (right * curSpeedY);

        // jump
        if (Input.GetButton("Jump") && canMove && (characterController.isGrounded || isOnWall || isSwimming))
        {
            moveDirection.y = jumpSpeed * (isOnWall ? 2f : 1f);
        }
        else
        {
            moveDirection.y = movementDirectionY;
        }

        // gravity
        if (!characterController.isGrounded)
        {
            moveDirection.y -= gravity * Time.deltaTime * (isSwimming ? 0.1f : 1f);
        }

        // perform movement
        characterController.Move(moveDirection * Time.deltaTime);

        // rotation
        if (canMove)
        {
            rotationX += -Input.GetAxis("Mouse Y") * lookSpeed;
            rotationX = Mathf.Clamp(rotationX, -lookXLimit, lookXLimit);
            playerCamera.transform.localRotation = Quaternion.Euler(rotationX, 0, 0);
            transform.rotation *= Quaternion.Euler(0, Input.GetAxis("Mouse X") * lookSpeed, 0);
        }

        // show inventory
        InventoryInterface.GetComponent<CanvasGroup>().alpha = (Input.GetKey("tab") ? 1f : 0f);

        // monolith interface
        if (Input.GetKeyDown(KeyCode.Space) || Input.GetKeyDown(KeyCode.Escape))
            MonolithInterface.GetComponent<MonolithInterfaceBehavior>().Hide();
        else if (Input.GetKeyDown(KeyCode.Q))
            MonolithInterface.GetComponent<MonolithInterfaceBehavior>().PressQ();
        else if (Input.GetKeyDown(KeyCode.E))
            MonolithInterface.GetComponent<MonolithInterfaceBehavior>().PressE();

        // building interface
        if (Input.GetKeyDown(KeyCode.C))
            BuildingInterface.GetComponent<BuildingInterfaceBehavior>().Prev();
        else if (Input.GetKeyDown(KeyCode.V))
            BuildingInterface.GetComponent<BuildingInterfaceBehavior>().Next();

        // build
        if (Input.GetKeyDown(KeyCode.B))
        {
            var buildingID = BuildingInterface.GetComponent<BuildingInterfaceBehavior>().CurrentBuildingID;
            Level.GetComponent<Level>().Build(buildingID);
        }

        // inventory button interface
        if (Input.GetKeyDown(KeyCode.F) || Input.mouseScrollDelta.magnitude > 0)
            InventoryButtonInterface.GetComponent<InventoryButtonBehavior>().Next();
        else if (Input.GetKeyDown(KeyCode.G) || Input.mouseScrollDelta.magnitude < 0)
            InventoryButtonInterface.GetComponent<InventoryButtonBehavior>().Prev();

        // quest interface
        if (Input.GetKeyDown(KeyCode.K))
        {
            QuestInterface.GetComponent<QuestBehavior>().Deliver();
        }
    }

}
