package com.k_int.aggr2.mimsy.data.hdo;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.Session;

import com.k_int.mimsy.ref.DataException;
import com.k_int.mimsy.ref.DataStatusEnum;
import com.k_int.mimsy.ref.MimsyDataTypeEnum;
import com.k_int.mimsy.ref.ObjectConformanceEnum;
import com.k_int.mimsy.ref.OriginatorEnum;

@Entity
@Table(name="CIIM_DATA_CONTEXT")
@PrimaryKeyJoinColumn(name="BASE_DATA_FK")
public class CIIMDataContextHDO extends BaseMimsyDataHDO
{
	private static final long serialVersionUID = 1L;
	private CIIMDataContextMetadataHDO metadata;
	private MimsyCuratedGroupHDO group;
	
	// all of these now separate to get around Glassfish hibernate issue
	private MimsyAgentDataHDO 		agent;
	private MimsyEventDataHDO 		event;
	private MimsyMediaDataHDO 		media;
	private MimsyObjectDataHDO 		object;
	private MimsyPlaceDataHDO 		place;
	private MimsyPublicationDataHDO publication;
	private MimsySiteDataHDO 		site;
	private MimsySubjectDataHDO 	subject;
	
	private String data_identifier;

	private OriginatorEnum originator;
	
	protected CIIMDataContextHDO()
	{;}
	
	protected CIIMDataContextHDO(String identifier,BaseMimsyDataHDO master,MimsyCuratedGroupHDO group,Date last_updated, OriginatorEnum originator)
	{
		super(identifier,MimsyDataTypeEnum.DATA_CONTEXT,last_updated,ObjectConformanceEnum.CORE);
		setMaster(master);
		this.group=group;
		this.originator=originator;
	}
	
	
	@OneToOne
	public CIIMDataContextMetadataHDO getCIIMMetadata()
	{
		return metadata;
	}
	
	@Column(name="DATA_IDENTIFIER")
	public String getDataIdentifier()
	{
		return data_identifier;
	}
	
	protected void setDataIdentifier(String data_identifier)
	{
		this.data_identifier=data_identifier;
	}
	
	public void setCIIMMetadata(CIIMDataContextMetadataHDO metadata)
	{
		this.metadata=metadata;
	}
	
	
	@Transient
	public BaseMimsyDataHDO getMaster()
	{
		if(agent!=null)
			return agent;
		else if (event!=null)
			return event;
		else if (media!=null)
			return media;
		else if (object!=null)
			return object;
		else if (place!=null)
			return place;
		else if (publication!=null)
			return publication;
		else if (site!=null)
			return site;
		else if (subject!=null)
			return subject;
		else
			return null;
	}
	@Transient
	protected void clearMasterObjects()
	{
		agent=null;
		event=null;
		media=null;
		object=null;
		place=null;
		publication=null;
		site=null;
		subject=null;
		data_identifier=null;
	}
	
	@Transient
	protected void setMaster(BaseMimsyDataHDO master)
	{
		clearMasterObjects();
		data_identifier=master.getMimsyIdentifier();
		if(master.getDataType()==MimsyDataTypeEnum.AGENT)
			setAgent((MimsyAgentDataHDO)master);
		else if (master.getDataType()==MimsyDataTypeEnum.EVENT)
			setEvent((MimsyEventDataHDO)master);
		else if (master.getDataType()==MimsyDataTypeEnum.MEDIA)
			setMedia((MimsyMediaDataHDO)master);
		else if (master.getDataType()==MimsyDataTypeEnum.OBJECT)
			setObject((MimsyObjectDataHDO)master);
		else if (master.getDataType()==MimsyDataTypeEnum.PLACE)
			setPlace((MimsyPlaceDataHDO)master);
		else if (master.getDataType()==MimsyDataTypeEnum.PUBLICATION)
			setPublication((MimsyPublicationDataHDO)master);
		else if (master.getDataType()==MimsyDataTypeEnum.SITE)
			setSite((MimsySiteDataHDO)master);
		else if (master.getDataType()==MimsyDataTypeEnum.SUBJECT)
			setSubject((MimsySubjectDataHDO)master);
		else
			throw new RuntimeException("Unsupported data context type "+master.getClass());
			
	}
				
	protected void setAgent(MimsyAgentDataHDO agent)
	{
		this.agent=agent;
	}
	
	@OneToOne
	protected MimsyAgentDataHDO getAgent()
	{
		return agent;
	}
	
	
	protected void setEvent(MimsyEventDataHDO event)
	{
		this.event=event;
	}
	
	@OneToOne
	protected MimsyEventDataHDO getEvent()
	{
		return event;
	}
	
	
	
	protected void setMedia(MimsyMediaDataHDO media)
	{
		this.media=media;
	}
	
	@OneToOne
	protected MimsyMediaDataHDO getMedia()
	{
		return media;
	}
	

	protected void setObject(MimsyObjectDataHDO object)
	{
		this.object=object;
	}
	
	@OneToOne
	protected MimsyObjectDataHDO getObject()
	{
		return object;
	}
	
	protected void setPlace(MimsyPlaceDataHDO place)
	{
		this.place=place;
	}
	
	@OneToOne
	protected MimsyPlaceDataHDO getPlace()
	{
		return place;
	}
	
	
	protected void setPublication(MimsyPublicationDataHDO publication)
	{
		this.publication=publication;
	}
	
	@OneToOne
	protected MimsyPublicationDataHDO getPublication()
	{
		return publication;
	}
	
	protected void setSite(MimsySiteDataHDO site)
	{
		this.site=site;
	}
	
	@OneToOne
	protected MimsySiteDataHDO getSite()
	{
		return site;
	}
	
	protected void setSubject(MimsySubjectDataHDO subject)
	{
		this.subject=subject;
	}
	
	@OneToOne
	protected MimsySubjectDataHDO getSubject()
	{
		return subject;
	}
	

	@OneToOne
	public MimsyCuratedGroupHDO getGroup()
	{
		return group;
	}
	
	
	protected void setGroup(MimsyCuratedGroupHDO group)
	{
		this.group=group;
	}
	
	@Column(name="ORIGINATOR")
	@Enumerated(EnumType.ORDINAL)
	public OriginatorEnum getOriginator()
	{
		return originator;
	}
	
	public void setOriginator(OriginatorEnum originator)
	{
		this.originator=originator;
	}
	
	public static CIIMDataContextHDO lookupDataOrCreateStub(Session sess,
			String mimsy_identifier, MimsyCuratedGroupHDO group, MimsyObjectDataHDO base, OriginatorEnum originator) throws Exception, DataException 
	{
		CIIMDataContextHDO retval = (CIIMDataContextHDO)BaseMimsyDataHDO.lookup(sess, mimsy_identifier);
		 
		if(retval==null)
		{
			try
			{
				 retval=new CIIMDataContextHDO(mimsy_identifier,base, group, new Date(),originator);
				 retval.setChecksum(new Long(new Date().getTime()));
				 retval.setDataStatus(DataStatusEnum.LIVE);
				 CIIMDataContextMetadataHDO md = new CIIMDataContextMetadataHDO();
				 md.setBoost(new Integer(0));
				 sess.save(md);
				 retval.setCIIMMetadata(md);
				 sess.save(retval);
				 sess.flush();
			}
			catch(Exception e)
			{
				throw new DataException(e);
			}
		}
		return retval;
	}
	
	public void clear()
	{
		super.clear();
	}
}
