using UnityEngine;

public class CarInputController : MonoBehaviour 
{
    public float TurnTime = 0.5f;
    public float TurnReleaseTime = 0.25f;

    private Engine engine;
    private Brakes brakes;
    private SteeringWheel steeringWheel;
    private Rigidbody2D r2;

    void Start()
    {
        engine = GetComponent<Engine>();
        brakes = GetComponent<Brakes>();
        steeringWheel = GetComponent<SteeringWheel>();
        r2 = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        if(NoInputs())
        {
            Stop();
        }
        else if(Gas() || Reverse())
        {
            PoweredDrive();
        }
        else
        {
            QuickTurnDrive();
        }
    }

    private void Stop()
    {
        engine.ThrottleFactor = 0f;
        brakes.BrakeFactor = 1;
        steeringWheel.SteeringFactor = 0;
    }

    private void PoweredDrive()
    {
        UpdateGasBrake();
        UpdateSteering();
    }

    private void QuickTurnDrive()
    {
        if (SteeringLeft())
            steeringWheel.SteeringFactor = -1.65f;
        else if (SteeringRight())
            steeringWheel.SteeringFactor = 1.65f;
        else
            steeringWheel.SteeringFactor = 0f;

        engine.ThrottleFactor = ((steeringWheel.SteeringFactor != 0) ? 0.85f : 0)
                                + ((Turbo()) ? 0.85f : 0);

        brakes.BrakeFactor = 0;
    }

    private bool NoInputs()
    {
        return !Gas() && !Reverse() && !SteeringLeft() && !SteeringRight() && !Turbo();
    }

    //void Update_OLD ()
    //{
    //    UpdateGasBrake();
    //    UpdateSteering();
    //}

    private void UpdateGasBrake()
    {
        if (Gas())
        {
            engine.ThrottleFactor = 1f + ((Turbo()) ? 1f : 0);
            brakes.BrakeFactor = 0;
        }
        else if (Reverse())
        {
            engine.ThrottleFactor = -1f - ((Turbo()) ? 1f : 0); ;
            brakes.BrakeFactor = 0;
        }        
    }

    private void UpdateSteering()
    {
        float speedDampedSteering = 1 - Mathf.Clamp((r2.velocity.magnitude / 25), 0, 1);
        float normalSteering = 1;

        float finalSteering = normalSteering; // 0.5f * normalSteering + 0.5f * speedDampedSteering;

        if (SteeringLeft())
            steeringWheel.SteeringFactor = -finalSteering;
        else if (SteeringRight())
            steeringWheel.SteeringFactor = finalSteering;
        else
            ReleaseTurn();

        //if (SteeringLeft())
        //    TurnLeft();
        //else if (SteeringRight())
        //    TurnRight();
        //else
        //    ReleaseTurn();
    }

    private void TurnLeftBySpeed()
    {
        float speedDamping = 1 - Mathf.Clamp((r2.velocity.magnitude / 25), 0, 1);
    }

    private void TurnLeft()
    {
        float turnPerFrame = Time.deltaTime / TurnTime;

        if (steeringWheel.SteeringFactor > 0)
        {
            steeringWheel.SteeringFactor = -turnPerFrame;
        }
        else
        {
            steeringWheel.SteeringFactor = Mathf.Max(-1, steeringWheel.SteeringFactor - turnPerFrame);
        } 
    }

    private void TurnRight()
    {
        float turnPerFrame = Time.deltaTime / TurnTime;

        if (steeringWheel.SteeringFactor < 0)
        {
            steeringWheel.SteeringFactor = turnPerFrame;
        }
        else
        {
            steeringWheel.SteeringFactor = Mathf.Min(1, steeringWheel.SteeringFactor + turnPerFrame);
        }
    }

    private void ReleaseTurn()
    {
        float releasePerFrame = Time.deltaTime / TurnReleaseTime;

        if (steeringWheel.SteeringFactor > 0)
        {
            steeringWheel.SteeringFactor = Mathf.Max(0, steeringWheel.SteeringFactor - releasePerFrame);
        }
        else if (steeringWheel.SteeringFactor < 0)
        {
            steeringWheel.SteeringFactor = Mathf.Min(0, steeringWheel.SteeringFactor + releasePerFrame);
        }
    }

    private static bool SteeringLeft()
    {
        return Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow);
    }

    private static bool SteeringRight()
    {
        return Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow);
    }

    private static bool Gas()
    {
        return Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow);
    }

    private static bool Reverse()
    {
        return Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow);
    }

    private static bool Turbo()
    {
        return Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
    }
}
