package racoon.rsim.monitors;

import racoon.input.DOObjective;
import racoon.input.DesignObjectives;
import racoon.rsim.RSProtocol;

/**
 * Define classes that allows to measure the value of a custom {@link DOObjective}
 * for a given {@link RSProtocol}.
 * 
 * @author Guido Lena Cota <guido.lena@unimi.it>
 */
public abstract class DOMonitor {

	// FIELDS
	// ------------------------------------------------------------------------------------------

	/**
     * The names of the metrics.
     */
    protected String[] metricsName;

    /**
     * The values of the measurements.
     */
    protected double[] metricsMeasures;
	
	/** 
     * The identifier of the {@link RSProtocol} to observe. 
     */
    protected int protocolID;
    
    // INITIALIZATION
   	// ------------------------------------------------------------------------------------------

     /**
   	 * Default constructor.
   	 */
   	public DOMonitor(int protocolID, String metrics){
   		this.protocolID = protocolID;
   		metricsName = metrics.split(",");
   	}

  	// METHODS
  	// ------------------------------------------------------------------------------------------
  	
	/**
	 * Do the measurement of the {@link DOObjective}s associated with the monitor
	 * object that implements this interface. 
	 */
	public abstract void measure();
	
	/**
	 * Return the names of each metric in a tabular format (separation term: semi-colon).
	 */
	public abstract String metricsToString();
	
	/**
	 * Return the array of doubles that stores the value of each metric.
	 */
	public double[] getMeasurements() {
		return metricsMeasures;
	}
	
	/**
	 * Verify the achievement of the {@link DOObjective}s associated with the monitor
	 * object that implements this interface.
	 */
	public void verifyObjectives(){
		// verify the design objectives
		for(int i = 0; i < metricsName.length; i++){
			if(DesignObjectives.getObjective(metricsName[i]) != null){
				DesignObjectives.getObjective(metricsName[i]).verifyObjective(metricsMeasures[i]);
			}
		}
	}

	/**
	 * Return the measurements of each metric in a tabular format (separation term: semi-colon).
	 */
	public String measurementsToString(){
		StringBuffer measurements = new StringBuffer();
		for(int i = 0; i < metricsMeasures.length; i++)
			measurements.append(String.format("%.2f", metricsMeasures[i])).append(';');
		
		return measurements.toString();
	}
	
	/**
	 * Return a string with all metrics and associated values, in a human-readable way.
	 */
	public String toString() {
		StringBuffer output = new StringBuffer();
		output.append(this.getClass().getName() + "\n");
		
		for(int i = 0 ; i < metricsName.length ; i++){
			output.append(metricsName[i] + ":\t" + metricsMeasures[i] + "\n");
		}
		
		output.append('\n');
		
		return output.toString();
	}
}
