package org.msh.reports.variables;

import org.msh.reports.ReportElement;
import org.msh.reports.keys.Key;
import org.msh.reports.query.SQLDefs;

/**
 * Interface that must be implemented by classes that want to expose itself as a 
 * report variable. A report variable is displayed in the report resulting table.
 * 
 * @author Ricardo Memoria
 *
 */
public interface Variable extends ReportElement {

	/**
	 * Prepare the query to return the data necessary to be handled by the variable. 
	 * This method basically includes the fields to be returned, table joins and its restrictions (where clause)
	 * @param def are the fields
	 * @param iteration
	 */
	void prepareVariableQuery(SQLDefs def, int iteration);

	/**
	 * Convert a value returned from the database to another value. For example, a number that must be displayed as a string.
	 * if more than 1 value is expected from the argument, the value represents an array, so a cast to Object[] must be done.
	 * @param value the values returned from the query
     * @param iteration the iteration number
	 * @return the Key corresponding to the values
	 */
	Key createKey(Object value, int iteration);

	
	/**
	 * From the key created by the method <code>createKey()</code>, return the text to be displayed in the table cell
	 * @param key is the object key created by the method <code>createKey()</code>
	 * @return the text to be displayed for the key
	 */
	String getDisplayText(Key key);

	/**
	 * Compare two values of the variable. It follows the implementation of the {@link Comparable} interface. If more than 1 field is specified
	 * to be returned from the data base, the parameters objects are actually an array of objects, so a proper cast must be done to the right value.
	 * <p>
	 * If just one field is specified, so val1 and val2 will point to this value
	 * @param val1
	 * @param val2
	 * @return
	 */
	int compareValues(Key val1, Key val2);


	/**
	 * Return the possible list of values of the variable. This list is used to initialize the data table
	 * @return list of object keys that will be used to create a fix list of values in the indicator
	 */
	Object[] getDomain();
	
	/**
	 * If the variable must display information in a two-level structure, so this method must return true
	 * @return true if variable is grouped
	 */
	boolean isGrouped();

	/**
	 * Convert a group object key to a text to be displayed to the user
	 * @param key is the group key created before by <code>createGroupKey()</code> method
	 * @return a text ready for displaying representing the key
	 */
	String getGroupDisplayText(Key key);
	
	/**
	 * Return the number of iterations that this variable will be called, i.e,
	 * the number of times the report will query the database using different
	 * conditions based on its iteration. 
	 * 
	 * @return the number of iterations this variable will be executed. If it supports
	 * just one iteration, return a value equals or lower than 1
	 */
	int getIteractionCount();
	
	/**
	 * Return true if the total of the values can be achieved by calculating
	 * the sum of the values. If false, the total will not be calculated
	 * @return true if total can be calculated by summing the values, otherwise
	 * returns false if the total doesn't exist
	 */
	boolean isTotalEnabled();
	
	
	/**
	 * Return the unit of measure returned by the variable. Example, patients, cases, exams, etc.
	 * Object can be anything that represents this unit. It's basically used to compare
	 * if a variable is compatible with another variable
	 * @return unit type
	 */
	Object getUnitType();
	
	
	/**
	 * Return the label of the units used in the variable to measure the numbers returned
	 * @return display label of the units used by the variable
	 */
	String getUnitTypeLabel();
}
