import java.util.*;

/**
 * The Resource class is used to describe the base class by which
 * all Shovels, Crushers and Trucks.
 * 
 * @author Ahmed Messaoud
 *
 */
public abstract class  Resource extends Thread{
	private String name;
	private boolean continueRunning = true;
	
	private long idleTime = 0;
	private long timeStamp = 0;
	
	/**
	 * @param name The name of the resource
	 */
	public Resource(String name){
		this.name = name;
	}
	
	/**
	 * Starts the idleling process of the resource.
	 * The idling is used to describe when a specific resource is not performing any actions, in this case, waiting in the queue to be processed
	 * 
	 * @throws AlreadyIdlelingException The Exception is thrown when 
	 */
	public void startIdleling() throws AlreadyIdlelingException{
		if( timeStamp == 0 )
			timeStamp = System.currentTimeMillis();
		else
			throw new AlreadyIdlelingException();
	}
	
	/**
	 * Stops the idleling process of the resource
	 * The idling is used to describe when a specific resource is not performing any actions, in this case, waiting in the queue to be processed
	 * 
	 * @throws NotIdlelingException
	 */
	public void stopIdleling() throws NotIdlelingException{
		if( timeStamp != 0 ){
			idleTime += (System.currentTimeMillis() - timeStamp);
			timeStamp = 0;
		}else
			throw new NotIdlelingException();
			
	}
	
	/**
	 * @return The idleling time in milliseconds
	 */
	public long getIdleTime(){
		return idleTime;
	}
	
	/**
	 * @return Wether the resource is currently idleling
	 */
	public boolean isIdleling(){
		return timeStamp != 0;
	}
	
	/**
	 * Set wether you want the thread to terminate at its next iteration.
	 * 
	 * @param b Boolean value stating thread termination
	 * @see Resource#getContinueRunning()
	 */
	public void setContinueRunning(boolean b){
		this.continueRunning = b;
	}
	
	/**
	 * @return The Boolean value stating wether the Resource will be terminated at its next iteration
	 * @see Resource#setContinueRunning
	 */
	public boolean getContinueRunning(){
		return this.continueRunning;
	}
	
	public abstract void run();
	
	/**
	 * Sends back the sleep time using the scale 100ms = 1min
	 * 
	 * @param time The constant time (in minutes)
	 * @param error The error for which the interval is set (ie +- 0.5 mins)
	 * @return The sleep time in milliseconds
	 */
	public long getSleepTime(double time, double error){
		if( error == 0 )
			return (long)(time * 100);
		return (long)((time-error+2*error*Math.random())*100);
	}
	
	/**
	 * @return The name of the Resource
	 */
	public String getResourceName(){
		return name;
	}
}
