/*******************************************************************************
 * This file is part of GECAMed.
 * 
 * GECAMed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (L-GPL) as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GECAMed is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License (L-GPL)
 * along with GECAMed.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * GECAMed is Copyrighted by the Centre de Recherche Public Henri Tudor (http://www.tudor.lu)
 * (c) CRP Henri Tudor, Luxembourg, 2008
 *******************************************************************************/
package lu.tudor.santec.gecamed.reporting.ejb.entity.beans;

import java.util.Collection;
import java.util.Vector;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import lu.tudor.santec.gecamed.core.ejb.entity.beans.GECAMedEntityBean;
import lu.tudor.santec.gecamed.reporting.ejb.entity.beans.ReportParameter.EmptyParameterException;


@NamedQueries(
{
	@NamedQuery(name = Report.FIND_ALL_REPORTS,			query = "SELECT OBJECT(o) FROM Report o"), 
	@NamedQuery(name = Report.FIND_REPORT_BY_NAME,		query = "SELECT OBJECT(o) FROM Report o WHERE o.name = :name"),
	@NamedQuery(name = Report.FIND_ALL_REPORT_TYPES,	query = "SELECT DISTINCT(r.type) FROM Report r"),
	@NamedQuery(name = Report.FIND_ALL_REPORT_NAMES,	query = "SELECT DISTINCT(r.name) FROM Report r")
})

@Entity
@Table(name = "report", schema = "reporting")
public class Report extends GECAMedEntityBean
{
	/* ======================================== */
	// 		CONSTANTS
	/* ======================================== */
	
	private static final long	serialVersionUID	= 1L;
	
	public static final String FIND_ALL_REPORT_TYPES	= "findAllReportTypes";
	public static final String FIND_ALL_REPORTS			= "findAllReports";
	public static final String FIND_REPORT_BY_NAME		= "findReportByName";
	public static final String FIND_ALL_REPORT_NAMES	= "findAllReportNames";
	
	
	
	/* ======================================== */
	// 		MEMBERS
	/* ======================================== */
	
	private String	name		= "";
	
	private Boolean	nativeQuery	= Boolean.TRUE;
	
	private String	type;
	
	private String	description;
	
	private String	query;
	
	private byte[]	jrxml;
	
	private byte[]	jasper;
	
	private Collection<ReportParameter>	parameter;
	
	// TRANSIENT
	private String	modifiedQuery;
	
	private Vector<Vector<Object>>		data;
	
	
	/* ======================================== */
	// 		GETTER & SETTER
	/* ======================================== */
	
	/**
	 * @return Returns the type.
	 */
	@Column(name = "type")
	public String getType()
	{
		return type;
	}
	
	
	/**
	 * @param type The type to set.
	 */
	public void setType(String type)
	{
		this.type = type;
	}
	
	
	/**
	 * @return Returns the name.
	 */
	@Column(name = "name")
	public String getName()
	{
		return name;
	}
	
	
	/**
	 * @param name The name to set.
	 */
	public void setName(String name)
	{
		this.name = name;
	}
	
	
	/**
	 * Currently only native queries are implemented, so this doesn't exist in the DB<br>
	 * and other values are not supported, yet.
	 * 
	 * @return always <code>true</code>
	 */
	@Transient
	public Boolean isNativeQuery()
	{
		return nativeQuery;
	}
	
	
//	@Transient
//	public void setNativeQuery(Boolean isNative)
//	{
//		this.nativeQuery = isNative;
//	}
	
	
	@Column(name = "query")
	public String getQuery()
	{
		return query;
	}
	
	
	public void setQuery(String query)
	{
		this.query = query;
	}
	
	
	@Column(name = "description")
	public String getDescription()
	{
		return description;
	}
	
	
	public void setDescription(String description)
	{
		this.description = description;
	}
	
	
	/**
	 * @return Returns the jasper.
	 */
	@Column(name = "jasper")
	public byte[] getJasper()
	{
		return jasper;
	}
	
	
	/**
	 * @param jasper The jasper to set.
	 */
	public void setJasper(byte[] jasper)
	{
		this.jasper = jasper;
	}
	
	
	/**
	 * @return Returns the jrxml.
	 */
	@Column(name = "jrxml")
	public byte[] getJrxml()
	{
		return jrxml;
	}
	
	
	/**
	 * @param jrxml The jrxml to set.
	 */
	public void setJrxml(byte[] jrxml)
	{
		this.jrxml = jrxml;
	}
	
	
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@JoinColumn(name = "report_id")
	public Collection<ReportParameter> getParameter ()
	{
		return parameter;
	}
	
	
	public void setParameter (Collection<ReportParameter> parameter)
	{
		this.parameter	= parameter;
	}
	
	
	
	/* ======================================== */
	// 		TRANSIENT OPERATIONS
	/* ======================================== */
	
	
	@Transient
	public String getModifiedQuery ()
	{
		return modifiedQuery;
	}
	
	
	@Transient
	public void setModifiedQuery (String query)
	{
		this.modifiedQuery = query;
	}
	
	
	@Transient
	public Vector<Vector<Object>> getData ()
	{
		return data;
	}
	
	
	@Transient
	public void setData (Vector<Vector<Object>> data)
	{
		this.data = data;
	}
	
	
	@Transient
	public String createFilledQuery () throws EmptyParameterException
	{
		String	query		= this.query;
		String	name;
		String	regEx;
		String	value;
		
		
		for (ReportParameter p : this.parameter)
		{
			name	= p.getName();
			value	= p.getSqlValue();
			
			regEx	= ":" + name + "(?=(\\W|\\Z))";
			query	= query.replaceAll(regEx, value);
		}
		
		return query.replaceAll(";(\\s|\\t|\\n|\\r)*\\Z", ";");
	}
	
	
	@Transient
	public String[] createFilledQueries () throws EmptyParameterException
	{
		return createFilledQuery().split(";");
	}
	
	
	@Transient
	public String getMendatoryParameterNames ()
	{
		StringBuilder	names	= new StringBuilder();
		
		
		for (ReportParameter p : this.parameter)
		{
			if (p.getMendatory())
				if (names.length() == 0)
					names.append(p.getName());
				else
					names.append(", ")
							.append(p.getName());
		}
		
		return names.toString();
	}
	
	
	@Override
	@Transient
	public String toString()
	{
		return this.name;
	}
	
	
	@Override
	@Transient
	public int compareTo(GECAMedEntityBean o)
	{
		Report	r;
		int		i;
		
		if (o == null)
			return 1;
		if (o instanceof Report)
		{
			r	= (Report) o;
			if (this.type == null && r.type == null)
				i	= 0;
			else if (this.type == null && r.type != null)
				i	= -1;
			else if (this.type != null && r.type == null)
				i	= 1;
			else
				i	= this.type.toLowerCase().compareTo(r.type.toLowerCase());
			
			if (i == 0)
				i	= this.name.compareTo(r.name);
			
			return i;
		}
		else
			return super.compareTo(o);
	}
	
	
//	@Override
//	@Transient
//	public Object clone()
//	{
//		Collection<ReportParameter> clonedParameters	= new HashSet<ReportParameter>();
//		Report						clone;
//		ReportParameter				clonedParameter;
//		
//		clone	= (Report) super.clone();
//		clone.setId(null);
//		
//		for (ReportParameter p : getParameter())
//		{
//			clonedParameter	= (ReportParameter) p.clone();
//			clonedParameter.setId(null);
//			clonedParameters.add(clonedParameter);
//		}
//		
//		clone.setParameter(clonedParameters);
//		
//		return clone;
//	}
}
