// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.core.modules.physics.util;

import javax.annotation.Nonnull;
import com.hypixel.hytale.math.vector.Vector3d;

public class PhysicsBodyStateUpdater
{
    protected static double MIN_VELOCITY;
    @Nonnull
    protected Vector3d acceleration;
    protected final ForceAccumulator accumulator;
    
    public PhysicsBodyStateUpdater() {
        this.acceleration = new Vector3d();
        this.accumulator = new ForceAccumulator();
    }
    
    public void update(@Nonnull final PhysicsBodyState before, @Nonnull final PhysicsBodyState after, final double mass, final double dt, final boolean onGround, @Nonnull final ForceProvider[] forceProvider) {
        this.computeAcceleration(before, onGround, forceProvider, mass, dt);
        updatePositionBeforeVelocity(before, after, dt);
        this.updateAndClampVelocity(before, after, dt);
    }
    
    protected static void updatePositionBeforeVelocity(@Nonnull final PhysicsBodyState before, @Nonnull final PhysicsBodyState after, final double dt) {
        after.position.assign(before.position).addScaled(before.velocity, dt);
    }
    
    protected static void updatePositionAfterVelocity(@Nonnull final PhysicsBodyState before, @Nonnull final PhysicsBodyState after, final double dt) {
        after.position.assign(before.position).addScaled(after.velocity, dt);
    }
    
    protected void updateAndClampVelocity(@Nonnull final PhysicsBodyState before, @Nonnull final PhysicsBodyState after, final double dt) {
        this.updateVelocity(before, after, dt);
        after.velocity.clipToZero(PhysicsBodyStateUpdater.MIN_VELOCITY);
    }
    
    protected void updateVelocity(@Nonnull final PhysicsBodyState before, @Nonnull final PhysicsBodyState after, final double dt) {
        after.velocity.assign(before.velocity).addScaled(this.acceleration, dt);
    }
    
    protected void computeAcceleration(final double mass) {
        this.acceleration.assign(this.accumulator.force).scale(1.0 / mass);
    }
    
    protected void computeAcceleration(@Nonnull final PhysicsBodyState state, final boolean onGround, @Nonnull final ForceProvider[] forceProviders, final double mass, final double timeStep) {
        this.accumulator.computeResultingForce(state, onGround, forceProviders, mass, timeStep);
        this.computeAcceleration(mass);
    }
    
    protected void assignAcceleration(@Nonnull final PhysicsBodyState state) {
        state.velocity.assign(this.acceleration);
    }
    
    protected void addAcceleration(@Nonnull final PhysicsBodyState state, final double scale) {
        state.velocity.addScaled(this.acceleration, scale);
    }
    
    protected void addAcceleration(@Nonnull final PhysicsBodyState state) {
        state.velocity.add(this.acceleration);
    }
    
    protected void convertAccelerationToVelocity(@Nonnull final PhysicsBodyState before, @Nonnull final PhysicsBodyState after, final double scale) {
        after.velocity.scale(scale).add(before.velocity).clipToZero(PhysicsBodyStateUpdater.MIN_VELOCITY);
    }
    
    static {
        PhysicsBodyStateUpdater.MIN_VELOCITY = 1.0E-6;
    }
}
