using System.Collections.Generic;
using UnityEngine;
using UnityEngine.VFX;
using UnityEngine.VFX.Utility;

public class PlayerMovement : MonoBehaviour
{
    [SerializeField]
    private float m_movementSpeed = 2f;

    [SerializeField]
    private float m_turnSpeed = 1f;

    [SerializeField]
    private float m_jumpforce = 10f;

    [SerializeField]
    private GameObject m_fireballPrefab;

    [SerializeField]
    private MagicMask m_mask;

    private Vector2 m_localEuler = Vector2.zero;

    private bool m_updatePlayer = false;

    private Rigidbody m_rb;



    // Start with air jump mask.
    private MaskType m_currentMask => m_mask.MaskType;
    private MaskType m_currentWeaponMask = MaskType.Red;

    public void SetPlayerActive(bool active)
    {
        Cursor.lockState = active ? CursorLockMode.Locked : CursorLockMode.None;
        Cursor.visible = !active;
        m_updatePlayer = active;
    }

    private void Awake()
    {
        m_mask.ActivateMask(m_currentWeaponMask);
        m_rb = GetComponent<Rigidbody>();
        var euler = transform.rotation.eulerAngles;
        m_localEuler.x = euler.x;
        m_localEuler.y = euler.y;
    }

    private void Update()
    {
        if (m_updatePlayer == false) return;
        PlayerActions();
        RotatePlayer();
        MovePlayer();
    }

    private void MovePlayer()
    {
        var d = Vector3.zero;
        if (Input.GetKey(KeyCode.W))
        {
            d.z = 1f;
        }
        else if (Input.GetKey(KeyCode.S))
        {
            d.z = -1f;
        }

        if (Input.GetKey(KeyCode.A))
        {
            d.x = -1f;
        }
        else if (Input.GetKey(KeyCode.D))
        {
            d.x = 1f;
        }

        // Disable faster strafe.
        if (d.x != 0f && d.z != 0f)
            d = d.normalized;

        var fwd = transform.forward;
        fwd.y = 0f;
        transform.Translate(fwd * m_movementSpeed * d.z * Time.fixedDeltaTime, Space.World);
        transform.Translate(transform.right * m_movementSpeed * d.x * Time.fixedDeltaTime, Space.World);
    }

    private void RotatePlayer()
    {
        m_localEuler.x += Input.GetAxis("Mouse X") * (m_turnSpeed * Time.fixedDeltaTime);
        if (m_localEuler.x < 0f) m_localEuler.x += 360f;
        else if (m_localEuler.x > 360f) m_localEuler.x -= 360f;

        m_localEuler.y -= Input.GetAxis("Mouse Y") * (m_turnSpeed * Time.fixedDeltaTime);
        if (m_localEuler.y < -90f) m_localEuler.y = -90f;
        else if (m_localEuler.y > 90f) m_localEuler.y = 90f;

        transform.rotation = Quaternion.Euler(m_localEuler.y, m_localEuler.x, 0f);
    }

    private void PlayerActions()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            PlayerJump();
        }

        if (Input.GetKeyDown(KeyCode.Q))
        {
            m_mask.ActivateMask(m_currentWeaponMask);
        }

        if (Input.GetKeyDown(KeyCode.E))
        {
            m_mask.ActivateMask(MaskType.Blue);
        }

        if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            UseMask();
        }
    }

    private void PlayerJump()
    {
        // Check if player sky jump mask
        if (m_currentMask != MaskType.Blue)
        {
            // Check if player is on platform.
            Ray _r = new Ray(transform.position, Vector3.down);
            var mask = (1 << 10);
            if (Physics.Raycast(_r, 1f, mask))
            {
                m_rb.AddForce(Vector3.up * m_jumpforce, ForceMode.Impulse);
            }
        }
        else
            m_rb.AddForce(Vector3.up * m_jumpforce, ForceMode.Impulse);
    }

    

    private void UseMask()
    {
        switch (m_currentMask)
        {
            case MaskType.Red:
                UseRedMask();
                break;

            case MaskType.Green:
                UseGreenMask();
                break;

            case MaskType.Purple:
                UsePurpleMask();
                break;

            case MaskType.Cyan:
                UseCyanMask();
                break;
        }
    }

    private void UseRedMask()
    {
        var _fwd = transform.forward;
        _fwd.y += 0.3f;
        FireBall(transform.position + transform.forward, _fwd, 1f);
    }

    private void UseGreenMask()
    {
        var _pos = transform.position + transform.forward;
        var _fwd = transform.forward;
        var _rig = transform.right;
        _fwd.y += 0.5f;
        FireBall(_pos, _fwd, 0.5f);
        FireBall(_pos + _rig / 5, _fwd + _rig, 0.5f);
        FireBall(_pos - _rig / 5, _fwd - _rig, 0.5f);
    }

    private void UseCyanMask()
    {
        var _fwd = transform.forward;
        _fwd.y += 0.1f;
        FireBall(transform.position + transform.forward, _fwd, 4f);
    }

    private void UsePurpleMask()
    {
        var _pos = transform.position + transform.forward;
        var _fwd = transform.forward;
        var _rig = transform.right;
        var _dir1_a = new Vector3(_fwd.x, _fwd.y + 0.5f, _fwd.z);
        var _dir1_b = new Vector3(_fwd.x, _fwd.y + 0.2f, _fwd.z);
        var _dir2_a = new Vector3(_fwd.x, _fwd.y + 0.4f, _fwd.z) + _rig / 2;
        var _dir2_b = new Vector3(_fwd.x, _fwd.y + 0.1f, _fwd.z) + _rig;
        var _dir3_a = new Vector3(_fwd.x, _fwd.y + 0.4f, _fwd.z) - _rig / 2;
        var _dir3_b = new Vector3(_fwd.x, _fwd.y + 0.1f, _fwd.z) - _rig;

        var _force = 1f;
        FireBall(_pos, _dir1_a, _force);
        FireBall(_pos, _dir1_b, _force);
        FireBall(_pos + _rig / 7, _dir2_a, _force);
        FireBall(_pos - _rig / 7, _dir3_a, _force);
        FireBall(_pos + _rig / 5, _dir2_b, _force);
        FireBall(_pos - _rig / 5, _dir3_b, _force);
    }

    private void FireBall(Vector3 position, Vector3 direction, float force)
    {
        var _ball = Instantiate(m_fireballPrefab);
        _ball.transform.position = position;
        _ball.GetComponent<FireBall>().LaunchFireBall(direction, force);
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.layer == 9)
        {
            if (collision.gameObject.TryGetComponent<MagicMask>(out var _mask))
            {
                m_mask.ActivateMask(_mask.MaskType);
                m_currentWeaponMask = _mask.MaskType;
                _mask.PickUpMask();
            }
        }
    }
}
