/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
// Package
package gov.va.med.fw.report;

// Java classes
import java.util.HashMap;
import java.util.Map;
import java.io.IOException;
import java.io.Serializable;

// Library classes
import org.apache.commons.lang.Validate;

// Framework classes
import gov.va.med.fw.report.data.QueryCriteria;
import gov.va.med.fw.security.UserPrincipal;

/**
 * Encapsulates configuration information to create a report
 *
 * Project: Framework</br>
 * Created on: 10:25:20 AM </br>
 *
 * @author DNS   LEV
 */
public class ReportConfiguration implements Serializable {

	public static final String DEFAULT_REPORT_TITLE = "Enrollment System Report";
	
	/**
	 * An instance of serialVersionUID
	 */
	private static final long serialVersionUID = 7728613580938640380L;

	/**
	 * A default report type is in PDF
	 */
	private ReportExportedType.Code reportOutputType = null;
	
	private String reportTitle = null;
	
	/**
	 * A report name
	 */
	private String reportName = null;
	
	/**
	 * A report id
	 */
	private String reportID = null;
	
	/**
	 * An instance of reportOutputName
	 */
	private String reportOutputName = null;

	/**
	 * A map containing key-value pairs of string resources
	 */
	private Map resourceMapping = null;
	
	/**
	 * A report criteria used to build a query string 
	 */
	private QueryCriteria queryCriteria = null;
	
	/**
	 * An instance of reportUser
	 */
	private UserPrincipal reportUser = null;
	
	/**
	 * A constructor to configure a report with a specific name, id and in PDF type
	 * A report name is used as a name of an output report file in PDF type.
	 * 
	 * @param name A report name
	 * @param ID A report ID
	 * @throws IOException
	 */
	public ReportConfiguration( String name, String ID ) throws IOException {
		this( name, ID, ReportExportedType.PDF );
	}

	/**
	 * A constructor to configure a report with a specific name and in a specific type.
	 * A report name and ID are used to form an output report file.
	 * 
	 * @param name A report name
	 * @param ID A report id
	 * @param type A report type
	 * @throws IOException Thrown in case of errors creating an output file 
	 */
	public ReportConfiguration( String name, String ID, ReportExportedType.Code type ) throws IOException {
		this( name, ID, type, getDefaultOutputFileName( name, ID, type ) );
	}
	
	/**
	 * A constructor to configure a report with a specific name,
	 * a specific output name, and in a specific type.
	 * 
	 * @param name A report name
	 * @param ID A report id
	 * @param type A report type
	 * @param output A report output name
	 * @throws IOException Thrown in case of errors creating an output file
	 */
	public ReportConfiguration( String name, String ID, ReportExportedType.Code type, String output ) throws IOException {
		
		Validate.notNull( name, "A report name must not be NULL" );
		Validate.notNull( ID, "A report ID must not be NULL" );
		Validate.notNull( type, "A report type must not be NULL" );
		Validate.notNull( output, "A report output stream must not be NULL" );
		
		this.reportName = name;
		this.reportID = ID;
		this.reportOutputType = type;
		this.reportOutputName = output;
	}

	/** Returns a user associated with this report
	 * @return A user associated with this report
	 */
	public UserPrincipal getReportUser() {
		return reportUser;
	}

	/** Sets a user associated with this report
	 * @param reportUser A user
	 */
	public void setReportUser(UserPrincipal reportUser) {
		this.reportUser = reportUser;
	}

	/** Returns a report type
	 * @return Returns the reportFormat.
	 */
	public ReportExportedType.Code getReportOutputType() {
		return reportOutputType;
	}

	/** Returns a report name
	 * @return Returns the reportName.
	 */
	public String getReportName() {
		return reportName;
	}

	/** Returns a report ID
	 * @return Returns the reportName.
	 */
	public String getReportID() {
		return reportID;
	}

	/** Returns a map containing a collection of key-value pairs 
	 * that might be used during a construction of a report
	 * 
	 * @return Returns the resourceMapping.
	 */
	public Map getResourceMapping() {
		return resourceMapping;
	}

	/** Sets a map containing a collection of key-value pairs 
	 * that might be used during a construction of a report
	 * 
	 * @param resourceMapping The resourceMapping to set.
	 */
	public void setResourceMapping(Map resourceMapping) {
		this.resourceMapping = resourceMapping;
	}
	
	/** This method adds an entry into resourceMapping.  
	 * that might be used during a construction of a report
	 * 
	 * @param resourceMapping The resourceMapping to set.
	 */
	public void addResourceMapping(Object key, Object value) {
		if(this.resourceMapping==null)
			this.resourceMapping=new HashMap();
		this.resourceMapping .put(key,value);
	}

	/**
	 * @return Returns the queryCriteria.
	 */
	public QueryCriteria getQueryCriteria() {
		return queryCriteria;
	}

	/**
	 * @param queryCriteria The reportCriteria to set.
	 */
	public void setQueryCriteria(QueryCriteria queryCriteria) {
		this.queryCriteria = queryCriteria;
	}

	/**
	 * @return Returns the reportOutputName.
	 */
	public String getReportOutputName() {
		return reportOutputName;
	}
	
	/**
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		StringBuffer info = new StringBuffer();
		info.append( "Report Name: " ).append( this.reportName )
			 .append( "Report ID: " ).append( this.reportID )
			 .append( "Generated report name: " ).append( this.reportOutputName )
			 .append( "Report Format ").append( this.reportOutputType.getAlias() );
		return info.toString();
	}
	

	/**
	 * @see java.lang.Object#finalize()
	 */
	protected void finalize() throws Throwable {
		this.queryCriteria = null;
		this.reportOutputType = null;
		this.reportID = null;
		this.reportName = null;
		if( this.resourceMapping != null ) {
			this.resourceMapping.clear();
		}
		this.resourceMapping = null;
	}

	/** Gets a default ouput file name for a report based on a report name and
	 * its type.
	 * 
	 * @param name A report's name
	 * @param ID A report's ID
	 * @param type A report's type
	 * @param output A report output file
	 * @return A report's file name
	 */
	private static String getDefaultOutputFileName( String name, String ID, ReportExportedType.Code type ) {

		Validate.notNull( name, "A report name must not be NULL" );
		Validate.notNull( ID, "A report ID must not be NULL" );
		Validate.notNull( type, "A report type must not be NULL" );
		
		return ID + "-" + name + "." + type.getAlias().toLowerCase(); 
	}

	public String getReportTitle() {
		return reportTitle;
	}

	public void setReportTitle(String reportTitle) {
		this.reportTitle = reportTitle;
	}
}