package mock.model.commandFactory;

import mock.model.MockBoat;
import mock.model.MockRace;
import mock.model.NewPolars;
import mock.model.VMG;

import java.util.Observable;

public class SailsCommand extends ObserverCommand {
    private boolean sailsOut;
    private double goalVelocity;

    public SailsCommand(MockRace race, MockBoat boat, boolean sailsOut) {
        super(race, boat);
        race.addVelocityCommand(this);
        this.sailsOut = sailsOut;
    }

    @Override
    public void execute() {
        this.boat.setSailsOut(this.sailsOut);
        boat.setVelocityDefault(false);

        if(sailsOut) {
            // Accelerate to VMG speed
            double polarSpeed = NewPolars.calculateSpeed(race.getWindDirection(), race.getWindSpeed(), boat.getBearing());
            VMG vmg = new VMG(polarSpeed, boat.getBearing());
            goalVelocity = vmg.getSpeed();
        } else {
            // Decelerate to 0
            goalVelocity = 0;
        }
    }

    @Override
    public void update(Observable o, Object arg) {
        double acceleration = 0.5;

        if(sailsOut && boat.getCurrentSpeed() < goalVelocity) {
            boat.setCurrentSpeed(Math.min(goalVelocity, boat.getCurrentSpeed() + acceleration));
        } else if (!sailsOut && boat.getCurrentSpeed() > goalVelocity) {
            // Apply deceleration to strictly 0 speed
            boat.setCurrentSpeed(Math.max(0, boat.getCurrentSpeed() - acceleration));
        } else {
            // Release boat from SailsCommand control
            if(sailsOut) boat.setVelocityDefault(true);
            race.deleteObserver(this);
        }
    }
}
