package de.hems.trafficsim;

import java.util.Random;

/**
 * Model class which represents a vehicle in the simulation.
 */
public class Vehicle {
    /**
     * a number to index the vehicle
     */
    protected int id;

    /**
     * current position of the vehicle on the track
     */
    protected float position;

    /**
     * current velocity of the vehicle
     */
    protected float curVelocity;

    /**
     * maximum velocity of the vehicle
     */
    protected float maxVelocity;

    /**
     * probability of the vehicle to brake without reason
     */
    protected float brakeProb;

    /**
     * length of the track the vehicle is placed on
     */
    protected float trackLength;

    /**
     * Constructs a new vehicle.
     *
     * @param id          a number to index the vehicle
     * @param position    current position of the vehicle on the track
     * @param maxVelocity maximum velocity of the vehicle
     * @param brakeProb   probability of the vehicle to brake without reason
     * @param trackLength length of the track the vehicle is placed on
     */
    public Vehicle(int id, int position, float maxVelocity, float brakeProb, float trackLength) {
        this.id = id;
        this.position = position;
        this.maxVelocity = maxVelocity;
        this.brakeProb = brakeProb;
        this.curVelocity = 0;
        this.trackLength = trackLength;

    }

    /**
     * Getter for position
     *
     * @return position
     */
    public float getPosition() {
        return position;
    }

    /**
     * Getter for curVelocity
     *
     * @return curVelocity
     */
    public float getCurVelocity() {
        return curVelocity;
    }

    /**
     * Getter for maxVelocity
     *
     * @return maxVelocity
     */
    public float getMaxVelocity() {
        return maxVelocity;
    }

    /**
     * Setter for maxVelocity
     *
     * @return maxVelocity
     */
    public void setMaxVelocity(float maxVelocity) {
        this.maxVelocity = maxVelocity;
    }

    /**
     * Setter for brakeProb
     *
     * @return brakeProb
     */
    public void setBrakeProb(float brakeProb) {
        this.brakeProb = brakeProb;
    }

    /**
     * Calculates the new velocity of the vehicle based on the following rules:
     * <ol>
     *     <li>Increase by one if the vehicle is slower than it's maximum speed</li>
     *     <li>Random brake by one</li>
     *     <li>Break if the distance to the forerunner is less than it's speed</li>
     * </ol>
     *
     * @param distanceForerunner distance to the forerunner of the vehicle
     */
    public void updateVelocity(float distanceForerunner) {
        Random random = new Random();

        float r = random.nextFloat();

        if (curVelocity < maxVelocity) {
            curVelocity = curVelocity + 1;
        }
        if (r < brakeProb && curVelocity > 0) {
            curVelocity = curVelocity - 1;
        }
        if (curVelocity > distanceForerunner) {
            curVelocity = distanceForerunner;
        }
    }

    /**
     * Updates the position of the vehicle according to it's previously calculated speed.
     */
    public void timeElapse() {
        position = (position + curVelocity) % this.trackLength;
    }

}

