﻿#if UNITY_EDITOR
using UnityEditor;
#endif
using PrismStudio;
using UnityEngine;

[ExecuteInEditMode]
public class MouseLook : MonoBehaviour
{
    public readonly string version = "1.5";

    public bool activated = false;

    public float lookSpeed = 2.0f;
    public float moveSpeed = 5.0f;
    public float boostMultiplier = 1.8f;
    public float smooth = 5.0f;

    private float smoothingFactor = 10f;
    private float inputA = 0.0f;
    private float inputD = 0.0f;
    private float inputW = 0.0f;
    private float inputS = 0.0f;
    private float inputQ = 0.0f;
    private float inputE = 0.0f;
    private float inputR = 0.0f;
    private float inputF = 0.0f;


    private float rotationX = 0.0f;
    private float rotationY = 0.0f; 
    private float tilt = 0.0f; 

    private Quaternion PrevRotation;

    public GameObject Point;
    public CameraProperty CameraProperty;

    private void OnEnable()
    {
        ForceEnable();
    }

    public void ForceEnable()
    {
        Point = transform.parent.parent.Find("Camera/Point").gameObject;
        CameraProperty = transform.parent.parent.Find("Camera").GetComponent<CameraProperty>();
    }

    private void Update()
    {
        if (!Application.isPlaying) return;

        Interpolate();

        activated = Input.GetMouseButton(1);

        if (activated)
        {
            Cursor.lockState = CursorLockMode.Locked;
            Cursor.visible = false;

            moveSpeed += Input.mouseScrollDelta.y * Time.deltaTime * 10;
            if (moveSpeed < 0) moveSpeed = 0;

            rotationX += Input.GetAxis("Mouse X") * lookSpeed;
            rotationY += Input.GetAxis("Mouse Y") * lookSpeed;
            rotationY = Mathf.Clamp(rotationY, -89.8f, 89.8f); // Limit vertical rotation

            tilt = transform.localRotation.eulerAngles.z + ((-inputR + inputF) * moveSpeed);

            // Rotate the camera
            transform.localRotation = Quaternion.AngleAxis(rotationX, Vector3.up);
            transform.localRotation *= Quaternion.AngleAxis(rotationY, Vector3.left);

            if (Input.GetMouseButton(0))
            {
                transform.localRotation = Quaternion.Lerp(PrevRotation, transform.rotation, smooth * Time.deltaTime);
            }

            transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, transform.localEulerAngles.y, tilt);

            // WASD movement
            Vector3 direction = new Vector3(-inputA + inputD, inputQ + -inputE, inputW + -inputS);
            direction = transform.TransformDirection(direction) * (moveSpeed * (Input.GetKey(KeyCode.LeftShift) ? 1.8f : 1f));

            // Update the camera position
            transform.position += direction * Time.deltaTime;

            Point.transform.SetPositionAndRotation(transform.position, transform.rotation);
        } else
        {
            Cursor.lockState = CursorLockMode.None;
            Cursor.visible = true;

            transform.SetPositionAndRotation(Point.transform.position, Point.transform.rotation);
        }
        PrevRotation = new Quaternion(transform.localRotation.x, transform.localRotation.y, transform.localRotation.z, transform.localRotation.w);
    }

    void Interpolate()
    {
        inputA = Mathf.Lerp(inputA, Input.GetKey(KeyCode.A) ? 1f : 0f, Time.deltaTime * smoothingFactor);
        inputD = Mathf.Lerp(inputD, Input.GetKey(KeyCode.D) ? 1f : 0f, Time.deltaTime * smoothingFactor);
        inputW = Mathf.Lerp(inputW, Input.GetKey(KeyCode.W) ? 1f : 0f, Time.deltaTime * smoothingFactor);
        inputS = Mathf.Lerp(inputS, Input.GetKey(KeyCode.S) ? 1f : 0f, Time.deltaTime * smoothingFactor);
        inputQ = Mathf.Lerp(inputQ, Input.GetKey(KeyCode.Q) ? 1f : 0f, Time.deltaTime * smoothingFactor);
        inputE = Mathf.Lerp(inputE, Input.GetKey(KeyCode.E) ? 1f : 0f, Time.deltaTime * smoothingFactor);
        inputR = Mathf.Lerp(inputR, Input.GetKey(KeyCode.R) ? 1f : 0f, Time.deltaTime * smoothingFactor);
        inputF = Mathf.Lerp(inputF, Input.GetKey(KeyCode.F) ? 1f : 0f, Time.deltaTime * smoothingFactor);
    }
}

#if UNITY_EDITOR

[CustomEditor(typeof(MouseLook))]
public class MouseLookEditor : Editor
{
    [SerializeField]
    MouseLook MouseLook;
    public override void OnInspectorGUI()
    {
        EditorGUILayout.LabelField("버전", ((MouseLook)target).version);

        GUILayout.Space(12);

        GUILayout.Label("Game 창에 우클릭하는 동안 마우스 잠금");

        GUILayout.Space(12);

        GUILayout.Label("WASD : 이동 (바라보는 방향으로)");
        GUILayout.Label("QE : 상하");
        GUILayout.Label("RF : 기울기");
        GUILayout.Label("마우스 휠스크롤 : 이동 속도");
        GUILayout.Label("마우스 왼클릭 : 마우스 스무스");

        GUILayout.Space(12);

        SerializedProperty look = serializedObject.FindProperty("lookSpeed");
        SerializedProperty move = serializedObject.FindProperty("moveSpeed");
        SerializedProperty boost = serializedObject.FindProperty("boostMultiplier");
        SerializedProperty smooth = serializedObject.FindProperty("smooth");

        look.floatValue = EditorGUILayout.FloatField("마우스 감도", look.floatValue);
        move.floatValue = EditorGUILayout.FloatField("움직임 속도", move.floatValue);
        boost.floatValue = EditorGUILayout.FloatField("움직임 가속 배수", boost.floatValue);
        smooth.floatValue = EditorGUILayout.FloatField("마우스 스무스 세기", smooth.floatValue);

        serializedObject.ApplyModifiedProperties();
    }
}

#endif