package net.ihe.xcpd.resp.model;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;
import net.ihe.gazelle.simulator.common.model.TestInstanceParticipants;
import net.ihe.gazelle.simulator.common.tf.model.Transaction;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.validator.NotNull;
import org.jboss.seam.Component;
import org.jboss.seam.annotations.Name;
/**
 *  Class Description :  XCPD Message
 *  XCPD Message
 *  
 * @class			XCPD Message
 * @author			Abderrazek Boufahja / INRIA Rennes IHE development Project
 * @see	> 			epoiseau@irisa.fr  -  http://www.ihe-europe.org
 * @version			1.0 - 2010, October 11th
 *
 */
@Entity
@Name("XCPDMessage")
@Table(name="xcpd_message", schema="public", uniqueConstraints=@UniqueConstraint(columnNames="id"))
@SequenceGenerator(name="xcpd_message_sequence", sequenceName="xcpd_message_id_seq", allocationSize=1)
public class XCPDMessage implements Serializable{
	
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    @Id
	@GeneratedValue(generator="xcpd_message_sequence", strategy=GenerationType.SEQUENCE)
	@NotNull
	@Column(name="id")
	private Integer id;
	
	@Temporal(TemporalType.TIMESTAMP)
	@Column(name="time_stamp")
	private Date timeStamp;
	
	@Column(name="message_response_content")
	private byte[] messageResponseContent;
	
	@Column(name="message_received_content")
	private byte[] messageReceivedContent;
	
	@Column(name="message_type")
	private String messageType;
	
	@ManyToOne
	@JoinColumn(name="transaction_id")
	private Transaction transaction;
	
	@ManyToOne
    @JoinColumn(name = "ip_to_country_id")
    private IpToCountry ipToCountry;
	
	@Column(name = "ip")
    private String ip;
	
	@ManyToOne
    @JoinColumn(name = "test_instance_participants_sender_id")
    private TestInstanceParticipants testInstanceParticipantsSender;
	
	/**
	 * Constructor
	 */
	
	public XCPDMessage(){
		
	}
	
	public XCPDMessage(Date timeStamp, byte[] messageResponseContent,
            byte[] messageReceivedContent, String messageType,
            Transaction transaction, IpToCountry ipToCountry, String ip,
            TestInstanceParticipants testInstanceParticipantsSender) {
        super();
        this.timeStamp = timeStamp;
        this.messageResponseContent = messageResponseContent;
        this.messageReceivedContent = messageReceivedContent;
        this.messageType = messageType;
        this.transaction = transaction;
        this.ipToCountry = ipToCountry;
        this.ip = ip;
        this.testInstanceParticipantsSender = testInstanceParticipantsSender;
    }
	public Date getTimeStamp() {
        return timeStamp;
    }
    public void setTimeStamp(Date timeStamp) {
        this.timeStamp = timeStamp;
    }
    public byte[] getMessageResponseContent() {
        return messageResponseContent;
    }
    public void setMessageResponseContent(byte[] messageResponseContent) {
        this.messageResponseContent = messageResponseContent;
    }
    public byte[] getMessageReceivedContent() {
        return messageReceivedContent;
    }
    public void setMessageReceivedContent(byte[] messageReceivedContent) {
        this.messageReceivedContent = messageReceivedContent;
    }
    public String getMessageType() {
        return messageType;
    }
    public void setMessageType(String messageType) {
        this.messageType = messageType;
    }
    public Transaction getTransaction() {
        return transaction;
    }
    public void setTransaction(Transaction transaction) {
        this.transaction = transaction;
    }
    public IpToCountry getIpToCountry() {
        return ipToCountry;
    }
    public void setIpToCountry(IpToCountry ipToCountry) {
        this.ipToCountry = ipToCountry;
    }
    public String getIp() {
        return ip;
    }
    public void setIp(String ip) {
        this.ip = ip;
    }
    public TestInstanceParticipants getTestInstanceParticipantsSender() {
        return testInstanceParticipantsSender;
    }
    public void setTestInstanceParticipantsSender(
            TestInstanceParticipants testInstanceParticipantsSender) {
        this.testInstanceParticipantsSender = testInstanceParticipantsSender;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
	/**
	 * @return
	 */
	public static List getAllReceivedMessages()
	{
		EntityManager em = (EntityManager) Component.getInstance("entityManager");
		Session session = (Session) em.getDelegate();
		Criteria criteria = session.createCriteria(XCPDMessage.class);
		criteria.add(Restrictions.isNotNull("relativeMessage"));
		List messages = criteria.list();
		if (messages != null && messages.size() > 0)
			return messages;
		else
			return null;
	}
	
	/**
	 * @param inRequest
	 * @return
	 */
	public static XCPDMessage getResponseRelativeToGivenRequest(XCPDMessage inRequest)
	{
		if (inRequest == null)
			return null;
		EntityManager em = (EntityManager) Component.getInstance("entityManager");
		Session session = (Session) em.getDelegate();
		Criteria criteria = session.createCriteria(XCPDMessage.class);
		criteria.add(Restrictions.ilike("relativeMessage", inRequest.getId()));
		List messages = criteria.list();
		if (messages != null && messages.size() > 0)
			return messages.get(0);
		else
			return null;
	}
	
	public static List getAllMessages() {
		EntityManager em = (EntityManager) Component.getInstance("entityManager");
		Session session = (Session) em.getDelegate();
		Criteria criteria = session.createCriteria(XCPDMessage.class);
		criteria.addOrder(Order.desc("timeStamp"));
		List messages = criteria.list();
		if (messages != null && messages.size() > 0)
			return messages;
		else
			return null;
	}
	@Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((ip == null) ? 0 : ip.hashCode());
        result = prime * result
                + ((ipToCountry == null) ? 0 : ipToCountry.hashCode());
        result = prime * result + Arrays.hashCode(messageReceivedContent);
        result = prime * result + Arrays.hashCode(messageResponseContent);
        result = prime * result
                + ((messageType == null) ? 0 : messageType.hashCode());
        result = prime
                * result
                + ((testInstanceParticipantsSender == null) ? 0
                        : testInstanceParticipantsSender.hashCode());
        result = prime * result
                + ((timeStamp == null) ? 0 : timeStamp.hashCode());
        result = prime * result
                + ((transaction == null) ? 0 : transaction.hashCode());
        return result;
    }
	@Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        XCPDMessage other = (XCPDMessage) obj;
        if (ip == null) {
            if (other.ip != null)
                return false;
        } else if (!ip.equals(other.ip))
            return false;
        if (ipToCountry == null) {
            if (other.ipToCountry != null)
                return false;
        } else if (!ipToCountry.equals(other.ipToCountry))
            return false;
        if (!Arrays
                .equals(messageReceivedContent, other.messageReceivedContent))
            return false;
        if (!Arrays
                .equals(messageResponseContent, other.messageResponseContent))
            return false;
        if (messageType == null) {
            if (other.messageType != null)
                return false;
        } else if (!messageType.equals(other.messageType))
            return false;
        if (testInstanceParticipantsSender == null) {
            if (other.testInstanceParticipantsSender != null)
                return false;
        } else if (!testInstanceParticipantsSender
                .equals(other.testInstanceParticipantsSender))
            return false;
        if (timeStamp == null) {
            if (other.timeStamp != null)
                return false;
        } else if (!timeStamp.equals(other.timeStamp))
            return false;
        if (transaction == null) {
            if (other.transaction != null)
                return false;
        } else if (!transaction.equals(other.transaction))
            return false;
        return true;
    }
	
	@Override
    public String toString() {
        return "XCPDMessage [id=" + id + ", timeStamp=" + timeStamp
                + ", messageResponseContent="
                + Arrays.toString(messageResponseContent)
                + ", messageReceivedContent="
                + Arrays.toString(messageReceivedContent) + ", messageType="
                + messageType + ", transaction=" + transaction
                + ", ipToCountry=" + ipToCountry + ", ip=" + ip
                + ", testInstanceParticipantsSender="
                + testInstanceParticipantsSender + "]";
    }
	
	public String getReceivedStringValue(){
	    if (this.messageReceivedContent == null) return null;
        String msgHL7 = new String(this.messageReceivedContent);
        return msgHL7;
    }
	
	public String getRespStringValue(){
	    if (this.messageResponseContent == null) return null;
        String msgHL7 = new String(this.messageResponseContent);
        return msgHL7;
    }
	
	public static XCPDMessage persistXCPDMessage(XCPDMessage res){
        EntityManager entityManager=(EntityManager)Component.getInstance("entityManager");
        res = entityManager.merge(res);
        entityManager.flush();
        return res;
    }
}