package com.k_int.generic.schema.hdo;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;

import com.k_int.generic.schema.ref.PropertyTypeEnum;

@Entity
@Table(name="SCHEMA_ELEMENT")
public class SchemaElementHDO implements Comparable<SchemaElementHDO>
{
	private Long id;	
	private Integer minOccurs = 0;
	private Integer maxOccurs = 1;
	private Long upperBound = null;
	private Long lowerBound = null;
	private Integer position = Integer.MAX_VALUE; //always last by default
	private String label = null;
	private String tooltip = null;
	private PropertyHDO prop = null;
	private String defaultValue = null;
	private Long schema_id = null;
	private PropertyTypeEnum override_type = null;
	private Boolean initialise_only = Boolean.FALSE;
	
	//Controlled List - Bank Specific
	private String bankURL = null;
	private String vocabulary = null;
	private String authority = null;
	
	//Controlled List - .properties File Specific
	private String propertyFileKey = null;

	protected SchemaElementHDO(){;}
	
	public SchemaElementHDO(PropertyHDO prop)
	{
		this.label = prop.getName();
		this.prop = prop;
	}

	@Id
	@Column(name="ID")
	@GeneratedValue(strategy=GenerationType.AUTO)
	public Long getId()
	{ 
		return id;                          
	} 
	
	protected void setId(Long id)
	{ 
		this.id = id;
	}
	
	@Column(name="MIN_OCCURS")
	public Integer getMinOccurs() 
	{
		return minOccurs;
	}

	public void setMinOccurs(Integer minOccurs) 
	{
		this.minOccurs = minOccurs;
	}

	@Column(name="MAX_OCCURS")
	public Integer getMaxOccurs() 
	{
		return maxOccurs;
	}

	public void setMaxOccurs(Integer maxOccurs) 
	{
		this.maxOccurs = maxOccurs;
	}
	
	@Column(name="LOWER_BOUND")
	public Long getLowerBound() 
	{
		return lowerBound;
	}
	
	public void setLowerBound(Long lowerBound) 
	{
		this.lowerBound = lowerBound;
	}
	
	@Column(name="UPPER_BOUND")
	public Long getUpperBound() 
	{
		return upperBound;
	}
	
	public void setUpperBound(Long upperBound) 
	{
		this.upperBound = upperBound;
	}
	
	@Column(name="POSITION")
	public Integer getPosition() 
	{
		return position;
	}

	public void setPosition(Integer position) 
	{
		this.position = position;
	}

	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="PROPERTY_FK")
	public PropertyHDO getProperty()
	{
		return prop;
	}

	public void setProperty(PropertyHDO prop) 
	{
		this.prop = prop;
	}
	
	@Column(name="LABEL")
	public String getLabel() 
	{
		return label;
	}

	public void setLabel(String label) 
	{
		this.label = label;
	}
	
	@Column(name="SCHEMA_FK")
	public Long getSchemaId() {
		return schema_id;
	}

	public void setSchemaId(Long schema_id) 
	{
		this.schema_id = schema_id;
	}
	
	@Column(name="TOOLTIP", length=1000)
	@Lob
	public String getTooltip() 
	{
		return tooltip;
	}

	public void setTooltip(String tooltip) 
	{
		this.tooltip = tooltip;
	}
	
	@Column(name="DEFAULT_VAL", length=2000)
	@Lob
	public String getDefaultValue() 
	{
		return defaultValue;
	}

	public void setDefaultValue(String defaultValue) 
	{
		this.defaultValue = defaultValue;
	}
	
	@Column(name="OVERRIDE_TYPE")
	@Enumerated(EnumType.ORDINAL) 
	public PropertyTypeEnum getOverrideType() 
	{
		return override_type;
	}

	public void setOverrideType(PropertyTypeEnum override_type) 
	{
		this.override_type = override_type;
	}
	
	@Column(name="INITIALISE_ONLY")
	public Boolean getInitialiseOnly() 
	{
		return initialise_only;
	}

	public void setInitialiseOnly(Boolean initialise_only) 
	{
		this.initialise_only = initialise_only;
	}
	
	@Column(name="BANK_URL")
	public String getBankURL()
	{
		return bankURL;
	}

	public void setBankURL(String bankURL)
	{
		this.bankURL = bankURL;
	}

	@Column(name="VOCABULARY")
	public String getVocabulary() 
	{
		return vocabulary;
	}

	public void setVocabulary(String vocabulary) 
	{
		this.vocabulary = vocabulary;
	}
	
	@Column(name="AUTHORITY")
	public String getAuthority() 
	{
		return authority;
	}

	public void setAuthority(String authority) 
	{
		this.authority = authority;
	}

	@Column(name="PROP_FILE_KEY")
	public String getPropertyFileKey() 
	{
		return propertyFileKey;
	}

	public void setPropertyFileKey(String propertyFileKey) 
	{
		this.propertyFileKey = propertyFileKey;
	}
	
	//LOOKUP BY ID
	public static SchemaElementHDO lookupOrCreate(Session session, Long schema_id, PropertyHDO prop)
	{
		SchemaElementHDO retval = SchemaElementHDO.lookup(session, schema_id, prop);
		
		if (retval == null) 
		{
			try
			{
				retval = new SchemaElementHDO(prop); 
				session.save(retval);
				session.flush();				 
			}
			catch (HibernateException he) 
			{
				throw new HibernateException(he);
			}    		 
		}
		return retval;
	}
	
	public static SchemaElementHDO lookupById(Session session, Long id)
	{		
		if(id == null)
		{
			return null;
		}
			
		try 
		{
			Query q = session.createQuery("Select x from com.k_int.generic.schema.hdo.SchemaElementHDO x where x.id = ?");
			q.setLong(0, id);
			
			return (SchemaElementHDO) q.uniqueResult();
		}
		catch (HibernateException he) 
		{
			throw new HibernateException(he);
		}    
	}
	
	public static SchemaElementHDO lookup(Session session, Long schema_id, PropertyHDO prop)
	{		
		if(schema_id == null || prop == null)
		{
			return null;
		}
			
		try 
		{
			Query q = session.createQuery("Select x from com.k_int.generic.schema.hdo.SchemaElementHDO x where x.schemaId = ? and x.property.id = ?");
			q.setLong(0, schema_id);
			q.setLong(1, prop.getId());
			
			return (SchemaElementHDO) q.uniqueResult();
		}
		catch (HibernateException he) 
		{
			throw new HibernateException(he);
		}    
	}
	
	/* Comparator method used for sorting */
	public int compareTo(SchemaElementHDO o) 
	{
        return this.position - o.position;
    }
}
