// Components/Crankshaft.cs
using System;

namespace FluidSim.Components
{
    public class Crankshaft
    {
        public double AngularVelocity { get; set; }   // rad/s
        public double CrankAngle { get; set; }        // rad, 0 … 4π (four‑stroke cycle)
        public double PreviousAngle { get; set; }     // ← now has public setter

        public double Inertia { get; set; } = 0.2;
        public double FrictionConstant { get; set; } = 0.0;      // N·m
        public double FrictionViscous { get; set; } = 0.000;     // N·m per rad/s

        private double externalTorque;

        public Crankshaft(double initialRPM = 400.0)
        {
            AngularVelocity = initialRPM * 2.0 * Math.PI / 60.0;
            CrankAngle = 0.0;
            PreviousAngle = 0.0;
        }

        public void AddTorque(double torque) => externalTorque += torque;

        public void Step(double dt)
        {
            // Catch NaN before it propagates
            if (double.IsNaN(AngularVelocity) || double.IsInfinity(AngularVelocity))
                AngularVelocity = 0.0;
            if (double.IsNaN(externalTorque) || double.IsInfinity(externalTorque))
                externalTorque = 0.0;

            PreviousAngle = CrankAngle;

            double friction = FrictionConstant * Math.Sign(AngularVelocity) + FrictionViscous * AngularVelocity;
            double netTorque = externalTorque - friction;
            double alpha = netTorque / Inertia;
            AngularVelocity += alpha * dt;

            if (AngularVelocity < 0) AngularVelocity = 0;

            CrankAngle += AngularVelocity * dt;

            if (CrankAngle >= 4.0 * Math.PI)
                CrankAngle -= 4.0 * Math.PI;
            else if (CrankAngle < 0)
                CrankAngle += 4.0 * Math.PI;

            externalTorque = 0.0;
        }
    }
}