package gov.va.med.esr.common.model.comms;

// Java Classes
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;

import gov.va.med.esr.common.model.CommonEntityKeyFactory;
import gov.va.med.esr.common.model.lookup.ComAACErrorType;
import gov.va.med.esr.common.model.lookup.ComAACRejectReasonType;
import gov.va.med.esr.common.model.lookup.ComLetterTemplateType;
import gov.va.med.esr.common.model.lookup.ComLetterType;
import gov.va.med.esr.common.model.lookup.ComMailingStatusType;
import gov.va.med.esr.common.model.lookup.ComMailingTriggerType;
import gov.va.med.esr.common.model.party.Address;
import gov.va.med.esr.common.model.person.Name;
import gov.va.med.esr.common.model.person.SSN;
import gov.va.med.esr.common.model.person.id.PersonIdEntityKey;
import gov.va.med.esr.common.util.CommonJspUtils;
import gov.va.med.fw.model.AbstractKeyedEntity;
import gov.va.med.fw.model.EntityKey;

/**
 * This class represents a comms mailing.
 *
 * @author DNS   TSAIG
 */
public class CommsLogEntry extends AbstractKeyedEntity {
	/**
	 *
	 */
	private static final long serialVersionUID = -4487158720694022048L;

	private static final String ACTION_COMMENT_SEPARATOR = System
			.getProperty("line.separator")
			+ System.getProperty("line.separator");

	/**
	 * Mailing recipient is the Veteran.
	 */
	public static final String RECIPIENT_VETERAN = "Veteran";

	/**
	 * Mailing recipient is the Spouse.
	 */
	public static final String RECIPIENT_SPOUSE = "Spouse";

	/**
	 * Mailing recipient is the Dependent.
	 */
	public static final String RECIPIENT_DEPENDENT = "Dependent";

	/**
	 * Mailing recipient is the Power of Attornet.
	 */
	public static final String RECIPIENT_POA = "Power of Attorney";

	/**
	 * Remail indicator of Resend.
	 */
	public static final String REMAIL_INDICATOR_RESEND = "RESEND";

	/**
	 * Remail indicator of Remailed.
	 */
	public static final String REMAIL_INDICATOR_REMAILED = "REMAILED";

	public static final String MAMUAL_TRIGGER_CODE = "1";
	public static final String REMAIL_TRIGGER_CODE = "2";
	public static final String HISTORICAL_TRIGGER_CODE = "3";
	public static final String AUTOMATIC_TRIGGER_CODE = "4";

	private static final String CANCEL_BY_HEC = "10";

	private String barcode = null;

	private String logXML = null;

	private String responseXML = null;

	private Date mailingDate = null;

	private BigDecimal workflowCaseId = null;

	private CommsTemplate template;

	private String actionComment = null;

	private ComAACRejectReasonType code1RejectReason = null;

	private List aacErrorReasonLinks = new ArrayList();

	private String remailIndicator = null;

	private List hecRejectionReasons = new ArrayList();

	private List mailingStatusLinks = new ArrayList();

	private ComLetterType letterType = null;

	private String recipient = null;

	private BigDecimal personId;

	private String aacExtractNumber;

	private Boolean overrideIndicator = null;

	private Address address = null;

	private SSN ssn = null;

	private Name name = null;

	private ComMailingTriggerType comMailingTriggerType = null;

	private Date ivmCaseClosureDate = null;

	private String ivmCaseNumber = null;

	private Boolean sentToIVM = null;

	public BigDecimal getPersonId() {
		return personId;
	}

	public void setPersonId(BigDecimal personId) {
		this.personId = personId;
	}

	public boolean isCancelledByHec() {
		return isTargetStatus(ComMailingStatusType.CANCEL_BY_HEC);
	}

	public boolean isMailedByAAC() {
		return isTargetStatus(ComMailingStatusType.MAILED_BY_AAC);
	}

	public boolean isSendToAAC() {
		return isTargetStatus(ComMailingStatusType.SEND_TO_AAC);
	}

	public boolean isSendToCMS() {
		return isTargetStatus(ComMailingStatusType.SEND_TO_CMS);
	}

	private boolean isTargetStatus(ComMailingStatusType.Code targetStatus) {
		MailingStatusLink statusLink = getLatestMailingStatus();
		ComMailingStatusType status = statusLink != null ? statusLink
				.getMailingStatus() : null;
		if (status != null && targetStatus.getCode().equals(status.getCode()))
			return true;
		return false;
	}

	public boolean isEligibleForRemail() {
		boolean isEligibleForRemail = true;
		MailingStatusLink statusLink = getLatestMailingStatus();
		ComMailingStatusType status = statusLink != null ? statusLink
				.getMailingStatus() : null;
		if (status != null
				&& (ComMailingStatusType.SEND_TO_AAC.getCode().equals(
						status.getCode())
						|| ComMailingStatusType.SENT_TO_AAC.getCode().equals(
								status.getCode())
						|| ComMailingStatusType.SEND_TO_CMS.getCode().equals(
								status.getCode()) || ComMailingStatusType.SENT_TO_CMS
						.getCode().equals(status.getCode())))
			isEligibleForRemail = false;
		return isEligibleForRemail;
	}

	public MailingStatusLink getLatestMailingStatus() {
		if (getMailingStatusLinks() == null
				|| getMailingStatusLinks().size() == 0)
			return null;

		return (MailingStatusLink) getMailingStatusLinks().get(0);
	}

	/**
	 * @return Returns the template.
	 */
	public CommsTemplate getTemplate() {
		return template;
	}

	/**
	 * @param template
	 *            The template to set.
	 */
	public void setTemplate(CommsTemplate template) {
		this.template = template;
	}

	public void applyTemplate(CommsTemplate template) {
		this.template = template;
		if (template != null) {
			this.letterType = template.getLetterType();

			this.recipient = RECIPIENT_VETERAN;
			String formNumber = template.getCommsTemplateFormNumber();
			if (formNumber.equals(ComLetterTemplateType.FORM_NUMBER_298
					.getCode())
					|| formNumber.equals(ComLetterTemplateType.FORM_NUMBER_299
							.getCode()))
				this.recipient = RECIPIENT_SPOUSE;
		}
	}

	/**
	 * @return Returns the aacErrorReasonLinks.
	 */
	public List getAacErrorReasonLinks() {
		return aacErrorReasonLinks;
	}

	/**
	 * @param aacErrorReasonLinks
	 *            The aacErrorReasons to set.
	 */
	public void setAacErrorReasonLinks(List aacErrorReasonLinks) {
		this.aacErrorReasonLinks = aacErrorReasonLinks;
	}

	/**
	 * @return Returns the actionComment.
	 */
	public String getActionComment() {
		return actionComment;
	}

	/**
	 * @param actionComment
	 *            The actionComment to set.
	 */
	public void setActionComment(String actionComment) {
		this.actionComment = actionComment;
	}

	public void addActionComment(String actionComment) {
		if (StringUtils.isNotBlank(actionComment)) {
			if (StringUtils.isNotBlank(getActionComment())) {
				StringBuffer buf = new StringBuffer();
				buf.append(actionComment);
				buf.append(ACTION_COMMENT_SEPARATOR);
				buf.append(getActionComment());
				setActionComment(buf.toString());
			} else {
				setActionComment(actionComment);
			}
		}
	}

	public String getLatestActionComment() {
		String latestActionComment = getActionComment();
		if (StringUtils.isNotBlank(latestActionComment)
				&& latestActionComment.indexOf(ACTION_COMMENT_SEPARATOR) != -1)
			latestActionComment = latestActionComment
					.split(CommonJspUtils.escapeRegExprChars(ACTION_COMMENT_SEPARATOR))[0];
		return latestActionComment;
	}

	/**
	 * @return Returns the code1RejectReason.
	 */
	public ComAACRejectReasonType getCode1RejectReason() {
		return code1RejectReason;
	}

	/**
	 * a convenient method to get the comms log id as String
	 *
	 * @return Returns the comms log id.
	 */
	public String getCommsLogIdString() {
		EntityKey key = getEntityKey();
		String keyVal = null;
		if (key != null)
			keyVal = key.getKeyValueAsString();
		return keyVal;
	}

	public PersonIdEntityKey getPersonIdEntityKey() {
		return personId != null ? CommonEntityKeyFactory
				.createPersonIdEntityKey(personId.toString()) : null;
	}

	/**
	 * @param code1RejectReason
	 *            The code1RejectReason to set.
	 */
	public void setCode1RejectReason(ComAACRejectReasonType code1RejectReason) {
		this.code1RejectReason = code1RejectReason;
	}

	/**
	 * @return Returns the formNumber.
	 */
	public String getFormNumber() {
		return (template == null) ? null : template
				.getCommsTemplateFormNumber();
	}

	/**
	 * @return Returns the hecRejectionReasons.
	 */
	public List getHecRejectionReasons() {
		return hecRejectionReasons;
	}

	/**
	 * @param hecRejectionReasons
	 *            The hecRejectionReasons to set.
	 */
	public void setHecRejectionReasons(List hecRejectionReasons) {
		this.hecRejectionReasons = hecRejectionReasons;
	}

	/**
	 * @return Returns the letterType.
	 */
	public ComLetterType getLetterType() {
		return letterType;
	}

	/**
	 * @param letterType
	 *            The letterType to set.
	 */
	public void setLetterType(ComLetterType letterType) {
		this.letterType = letterType;
	}

	/**
	 * @return Returns the ComMailingTriggerType.
	 */
	public ComMailingTriggerType getComMailingTriggerType() {
		return comMailingTriggerType;
	}

	/**
	 * @param comMailingTriggerType
	 *            The letterType to set.
	 */
	public void setComMailingTriggerType(
			ComMailingTriggerType comMailingTriggerType) {
		this.comMailingTriggerType = comMailingTriggerType;
	}

	/**
	 * @return Returns the logXML.
	 */
	public String getLogXML() {
		return logXML;
	}

	/**
	 * @param logXML
	 *            The logXML to set.
	 */
	public void setLogXML(String logXML) {
		this.logXML = logXML;
	}

	/**
	 * @return Returns the mailingDate.
	 */
	public Date getMailingDate() {
		return mailingDate;
	}

	/**
	 * @param mailingDate
	 *            The mailingDate to set.
	 */
	public void setMailingDate(Date mailingDate) {
		this.mailingDate = mailingDate;
	}

	/**
	 * @return Returns the mailingStatuses.
	 */
	public List getMailingStatusLinks() {
		return mailingStatusLinks;
	}

	/**
	 * @param mailingStatusLinks
	 *            The mailingStatuses to set.
	 */
	public void setMailingStatusLinks(List mailingStatusLinks) {
		this.mailingStatusLinks = mailingStatusLinks;
	}

	/**
	 * @return Returns the recipient.
	 */
	public String getRecipient() {
		return recipient;
	}

	/**
	 * @param recipient
	 *            The recipient to set.
	 */
	public void setRecipient(String recipient) {
		this.recipient = recipient;
	}

	/**
	 * @return Returns the remailIndicator.
	 */
	public String getRemailIndicator() {
		return remailIndicator;
	}

	/**
	 * @param remailIndicator
	 *            The remailIndicator to set.
	 */
	public void setRemailIndicator(String remailIndicator) {
		this.remailIndicator = remailIndicator;
	}

	/**
	 * @return Returns the responseXML.
	 */
	public String getResponseXML() {
		return responseXML;
	}

	/**
	 * @param responseXML
	 *            The responseXML to set.
	 */
	public void setResponseXML(String responseXML) {
		this.responseXML = responseXML;
	}

	/**
	 * @return Returns the templateName.
	 */
	public String getTemplateName() {
		return (template == null) ? null : template.getCommsTemplateName();
	}

	/**
	 * @return Returns the workload identifier.
	 */
	public BigDecimal getWorkflowCaseId() {
		return workflowCaseId;
	}

	/**
	 * @param workflowCaseId
	 *            The workflowCaseId to set.
	 */
	public void setWorkflowCaseId(BigDecimal workflowCaseId) {
		this.workflowCaseId = workflowCaseId;
	}

	/**
	 * @return Returns the aacExtractNumber.
	 */
	public String getAacExtractNumber() {
		return aacExtractNumber;
	}

	/**
	 * @param aacExtractNumber
	 *            The aacExtractNumber to set.
	 */
	public void setAacExtractNumber(String aacExtractNumber) {
		this.aacExtractNumber = aacExtractNumber;
	}

	/**
	 * @return Returns the overrideIndicator.
	 */
	public Boolean getOverrideIndicator() {
		return overrideIndicator;
	}

	/**
	 * @param overrideIndicator
	 *            The overrideIndicator to set.
	 */
	public void setOverrideIndicator(Boolean overrideIndicator) {
		this.overrideIndicator = overrideIndicator;
	}

	public SSN getSsn() {
		return ssn;
	}

	public void setSsn(SSN ssn) {
		this.ssn = ssn;
	}

	public Name getName() {
		return name;
	}

	public void setName(Name name) {
		this.name = name;
	}

	public void addMailingStatus(ComMailingStatusType mailingStatusType) {
		MailingStatusLink link = new MailingStatusLink();
		link.setCommsLog(this);
		link.setMailingStatus(mailingStatusType);
		mailingStatusLinks.add(0, link); // insert new ones always at the
											// beginning
	}

	public void addHecRejectReason(String hecRejReasonDesc) {
		HecRejectReason rejReason = new HecRejectReason(hecRejReasonDesc);
		rejReason.setCommsLog(this);
		hecRejectionReasons.add(rejReason);
	}

	public void addAacErrorReason(ComAACErrorType aacErrorReason) {
		AacErrorReasonLink link = new AacErrorReasonLink();
		link.setCommsLog(this);
		link.setAacErrorType(aacErrorReason);
		aacErrorReasonLinks.add(link);
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	/**
	 * Gets the barcode associated with this com mailing. This value will only
	 * be present once it is persisted to the database.
	 *
	 * @return The barcode.
	 */
	public String getBarcode() {
		return barcode;
	}

	/**
	 * Sets the barcode. This value must be set per the use case requirements so
	 * it should only be set upon saving the record to the database initially by
	 * the business service layer.
	 *
	 * @param barcode
	 *            The barcode to set.
	 */
	public void setBarcode(String barcode) {
		this.barcode = barcode;
	}


	public Date getIvmCaseClosureDate() {
		return ivmCaseClosureDate;
	}

	public void setIvmCaseClosureDate(Date ivmCaseClosureDate) {
		this.ivmCaseClosureDate = ivmCaseClosureDate;
	}

	public String getIvmCaseNumber() {
		return ivmCaseNumber;
	}

	public void setIvmCaseNumber(String ivmCaseNumber) {
		this.ivmCaseNumber = ivmCaseNumber;
	}

	public Boolean getSentToIVM() {
		return sentToIVM;
	}

	public void setSentToIVM(Boolean sentToIVM) {
		this.sentToIVM = sentToIVM;
	}

	protected void buildToString(ToStringBuilder builder) {
		super.buildToString(builder);
		builder.append("barcode", barcode);
		builder.append("logXML", logXML);
		builder.append("mailingDate", mailingDate);
		builder.append("workflowCaseId", workflowCaseId);
		builder.append("actionComment", actionComment);
		builder.append("code1RejectReason", code1RejectReason);
		builder.append("aacErrorReasonLinks", aacErrorReasonLinks);
		builder.append("remailIndicator", remailIndicator);
		builder.append("hecRejectionReasons", hecRejectionReasons);
		builder.append("mailingStatusLinks", mailingStatusLinks);
		builder.append("letterType", letterType);
		builder.append("recipient", recipient);
		builder.append("personId", personId);
		builder.append("aacExtractNumber", aacExtractNumber);
		builder.append("overrideIndicator", overrideIndicator);
		builder.append("comMailingTriggerType", comMailingTriggerType);
		builder.append("ivmCaseClosureDate", ivmCaseClosureDate);
		builder.append("sentToIVM", sentToIVM);
	}

}
