using System;
using UnityEngine;

namespace Controller.Bicycle
{
    public class RbBicycleController : BicycleControllerBaseBehaviour, IBicycleController
    {
        #region Variables

        private Transform rbTransform;
        private float currentSteerAngle;
        private float currentLeaningAngle;
        private float currentSpeed;

        public BicycleControllerMode ControllerMode
        {
            get => controllerMode;
            set => controllerMode = value;
        }

        public float CurrentSpeed
        {
            get => currentSpeed;
            set => currentSpeed = Mathf.Clamp(value, 0, maxSpeed);
        }

        public float CurrentSteerAngle
        {
            get => currentSteerAngle;
            set => currentSteerAngle = Mathf.Clamp(value, -maxSteeringAngle, maxSteeringAngle);
        }

        public float CurrentLeaningAngle
        {
            get => currentLeaningAngle;
            set
            {
                
                //don't lean while standing / walking to bike
                if (rigidBody.velocity.magnitude < .5f) return;
                currentLeaningAngle = Mathf.Clamp(value, -maxLeaningAngle, maxLeaningAngle);
            }
        }

        public Vector3 RigidBodyVelocity => rigidBody.velocity;

        #endregion

        private void Awake()
        {
            rbTransform = rigidBody.transform;
            rigidBody.freezeRotation = true;
            rigidBody.centerOfMass = centerOfMass.position;
        }

        private void Update()
        {
            //throw new NotImplementedException();
        }

        private void FixedUpdate()
        {
            ApplyVelocity();
            ApplySteerAngleAndRotation();
        }

        private void ApplyVelocity()
        {
            var targetVelocity = new Vector3(0, 0, CurrentSpeed);
            targetVelocity = rbTransform.TransformDirection(targetVelocity);
            var velocityChange = targetVelocity - rigidBody.velocity;
            velocityChange.y = 0;
            rigidBody.AddForce(velocityChange, ForceMode.VelocityChange);
        }

        private void ApplySteerAngleAndRotation()
        {
            //don't lean and rotate when veeeeeery sloooow/standing. Otherwise bike will rotate already
            if (CurrentSpeed < 0.3f) //ca 1 km/h
            {
                CurrentSteerAngle = 0;
                CurrentLeaningAngle = 0;
            }

            if (controllerMode == BicycleControllerMode.Independent)
            {
                var r = rbTransform.localRotation.eulerAngles;
                rbTransform.localRotation =
                    Quaternion.Euler(r + new Vector3(0, CurrentSteerAngle, -CurrentLeaningAngle) * Time.fixedDeltaTime);
            }
            else if (controllerMode == BicycleControllerMode.LeaningAngleDependentOnSteerAngle)
            {
                //TODO
            }
        }
    }
}