/********************************************************************
 * Copyright © 2005 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.esr.ui.demographic.action;

// Java Classes
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;

import javax.servlet.http.HttpServletRequest;

// Library Classes
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.util.MessageResources;

import gov.va.med.fw.ui.UIConstants;
// Framework Classes
import gov.va.med.fw.util.StringUtils;

// ESR Classes
import gov.va.med.esr.ui.ApplicationConstants.MessageKeys;
import gov.va.med.esr.ui.common.action.AddressForm;
import gov.va.med.esr.ui.common.util.JspUtils;
import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.infra.PreciseDateUtils;
import gov.va.med.esr.common.model.lookup.ConfidentialAddressCategoryType;
import gov.va.med.esr.common.model.lookup.EmailSourceOfChange;
import gov.va.med.esr.common.model.lookup.PhoneSourceOfChange;
import gov.va.med.esr.common.model.lookup.VAFacility;

/**
 * This is the form used in conjunction with the Demographics Addresses page.
 * 
 * @author Andrew Pach
 * @version 3.0
 */
public class DemographicAddressesForm extends AddressForm {
	private static final long serialVersionUID = -1911960767303598335L;

	private String permBadAddressReason;

	private String permAddrLastUpdate;

	private String permAddrSourceOfUpdate;

	private String permAddrSiteOfUpdate;
	private String FormattedConfAddrCategories;

	private Date permAddrStartDate;

	private Date permAddrEndDate;

	private List phoneId;

	private List phoneType;

	private List phoneNumber;

	private List phoneSourceOfUpdate;

	private List phoneSiteOfUpdate;

	private List phoneLastUpdate;

	private List emailId;

	private List emailType;

	private List emailAddress;

	private List emailSourceOfUpdate;

	private List emailSiteOfUpdate;

	private List emailLastUpdate;

	private List confAddrCategories;
	
	private String[] selectedConfAddrCategories;

	private Integer addEmailType;

	private Integer addPhoneType;

	private boolean confAddrCurrent = false;

	private boolean permAddrCurrent = false;

	private boolean tempAddrCurrent = false;

	private boolean confAddrInFuture = false;

	private boolean permAddrInFuture = false;

	private boolean tempAddrInFuture = false;

	private boolean confAddrInPast = false;

	private boolean permAddrInPast = false;

	private boolean tempAddrInPast = false;

	private boolean tempAddrPresent = false;

	private boolean confAddrPresent = false;

	private String addressType = null;

	// #294726-Confidential/Temporary addresses need start/end dates
	private String startDate;
	private String endDate;

	// Label constants
	public static final String TYPE_LABEL = "label.addresses.type";

	public static final String PHONE_NUMBER_LABEL = "label.addresses.phone";

	public static final String NUMBER_LABEL = "label.addresses.number";

	public static final String EMAIL_ADDRESS_LABEL = "label.addresses.email";

	public static final int MAX_PHONE_NUMBER_LENGTH = 20;

	/**
	 * Default constructor.
	 */
	public DemographicAddressesForm() {
		super();
		initialize();
	}

	/**
	 * Resets all the form data to null.
	 */
	public void reset(ActionMapping mapping, HttpServletRequest request) {
		super.reset(mapping, request);
		initialize();
	}

	/**
	 * Initializes the data on this form.
	 */
	protected void initialize() {
		super.initialize();
		phoneId = new ArrayList();
		phoneType = new ArrayList();
		phoneNumber = new ArrayList();
		phoneSourceOfUpdate = new ArrayList();
		phoneSiteOfUpdate = new ArrayList();
		phoneLastUpdate = new ArrayList();
		emailId = new ArrayList();
		emailType = new ArrayList();
		emailAddress = new ArrayList();
		emailSourceOfUpdate = new ArrayList();
		emailSiteOfUpdate = new ArrayList();
		emailLastUpdate = new ArrayList();
		confAddrCategories = new ArrayList();
		selectedConfAddrCategories =  new String[] {};
		permBadAddressReason = null;
		permAddrLastUpdate = null;
		permAddrSourceOfUpdate = null;
		permAddrSiteOfUpdate = null;
		permAddrStartDate = null;
		permAddrEndDate = null;
		confAddrCurrent = false;
		permAddrCurrent = false;
		tempAddrCurrent = false;
		confAddrInFuture = false;
		permAddrInFuture = false;
		tempAddrInFuture = false;
		confAddrInPast = false;
		permAddrInPast = false;
		tempAddrInPast = false;
		confAddrPresent = false;
		tempAddrPresent = false;

		startDate = null;
		endDate = null;
	}

	/**
	 * Adds a new phone number to the form.
	 */
	public void addNewPhone() {
		addPhone("", "", "", "", "", "");
	}

	/**
	 * Adds a new e-mail to the form.
	 */
	public void addNewEmail() {
		addEmail("", "", "", "", "", "");
	}

	/**
	 * Adds a phone to the list of phones.
	 * 
	 * @param phoneId
	 *            The phone Id
	 * @param phoneType
	 *            The phone type
	 * @param phoneNumber
	 *            The phone number
	 * @param phoneSourceOfUpdate
	 *            The phone source of update
	 * @param phoneSiteOfUpdate
	 *            The phone site of update
	 * @param phoneLastUpdate
	 *            The phone last update
	 */

	public Integer getAddEmailType() {
		return addEmailType;
	}

	public void setAddEmailType(Integer addEmailType) {
		this.addEmailType = addEmailType;
	}

	public Integer getAddPhoneType() {
		return addPhoneType;
	}

	public void setAddPhoneType(Integer addPhoneType) {
		this.addPhoneType = addPhoneType;
	}

	public void addPhone(String phoneId, String phoneType, String phoneNumber, String phoneSourceOfUpdate,
			String phoneSiteOfUpdate, String phoneLastUpdate) {
		// Default the source and site of change to HEC if one wasn't specified
		if (StringUtils.isBlank(phoneSourceOfUpdate)) {
			phoneSourceOfUpdate = PhoneSourceOfChange.CODE_HEC.getName();
		}
		if (StringUtils.isBlank(phoneSiteOfUpdate)) {
			phoneSiteOfUpdate = VAFacility.CODE_HEC.getName();
		}

		this.phoneId.add(phoneId);
		this.phoneType.add(phoneType);
		this.phoneNumber.add(phoneNumber);
		this.phoneSourceOfUpdate.add(phoneSourceOfUpdate);
		this.phoneSiteOfUpdate.add(phoneSiteOfUpdate);
		this.phoneLastUpdate.add(phoneLastUpdate);
	}

	/**
	 * Adds a email to the list of emails.
	 * 
	 * @param emailId
	 *            The email Id
	 * @param emailType
	 *            The email type
	 * @param emailAddress
	 *            The email address
	 * @param emailSourceOfUpdate
	 *            The email source of update
	 * @param emailSiteOfUpdate
	 *            The email site of update
	 * @param emailLastUpdate
	 *            The email last update
	 */
	public void addEmail(String emailId, String emailType, String emailAddress, String emailSourceOfUpdate,
			String emailSiteOfUpdate, String emailLastUpdate) {
		// Default the source of change to HEC if one wasn't specified
		if (StringUtils.isBlank(emailSourceOfUpdate)) {
			emailSourceOfUpdate = EmailSourceOfChange.CODE_HEC.getName();
		}
		if (StringUtils.isBlank(emailSiteOfUpdate)) {
			emailSiteOfUpdate = VAFacility.CODE_HEC.getName();
		}

		this.emailId.add(emailId);
		this.emailType.add(emailType);
		this.emailAddress.add(emailAddress);
		this.emailSourceOfUpdate.add(emailSourceOfUpdate);
		this.emailSiteOfUpdate.add(emailSiteOfUpdate);
		this.emailLastUpdate.add(emailLastUpdate);
	}

	public int getPhoneSize() {
		return phoneId.size();
	}

	public int getEmailSize() {
		return emailId.size();
	}

	public String getPhoneId(int index) {
		return (String) phoneId.get(index);
	}

	public List getPhoneIdList() {
		return phoneId;
	}

	public void setPhoneId(int index, String phoneId) {
		setElement(this.phoneId, index, phoneId);
	}

	public void setPhoneIdList(List phoneId) {
		this.phoneId = phoneId;
	}

	public String getPhoneType(int index) {
		return (String) phoneType.get(index);
	}

	public List getPhoneTypeList() {
		return phoneType;
	}

	public void setPhoneType(int index, String phoneType) {
		setElement(this.phoneType, index, phoneType);
	}

	public void setPhoneTypeList(List phoneType) {
		this.phoneType = phoneType;
	}

	public String getPhoneNumber(int index) {
		return (String) phoneNumber.get(index);
	}

	public List getPhoneNumberList() {
		return phoneNumber;
	}

	public void setPhoneNumber(int index, String phoneNumber) {
		setElement(this.phoneNumber, index, phoneNumber);
	}

	public void setPhoneNumberList(List phoneNumber) {
		this.phoneNumber = phoneNumber;
	}

	public String getPhoneSourceOfUpdate(int index) {
		return (String) phoneSourceOfUpdate.get(index);
	}

	public List getPhoneSourceOfUpdateList() {
		return phoneSourceOfUpdate;
	}

	public void setPhoneSourceOfUpdate(int index, String phoneSourceOfUpdate) {
		setElement(this.phoneSourceOfUpdate, index, phoneSourceOfUpdate);
	}

	public void setPhoneSourceOfUpdateList(List phoneSourceOfUpdate) {
		this.phoneSourceOfUpdate = phoneSourceOfUpdate;
	}

	public String getPhoneSiteOfUpdate(int index) {
		return (String) phoneSiteOfUpdate.get(index);
	}

	public List getPhoneSiteOfUpdateList() {
		return phoneSiteOfUpdate;
	}

	public void setPhoneSiteOfUpdate(int index, String phoneSiteOfUpdate) {
		setElement(this.phoneSiteOfUpdate, index, phoneSiteOfUpdate);
	}

	public void setPhoneSiteOfUpdateList(List phoneSiteOfUpdate) {
		this.phoneSiteOfUpdate = phoneSourceOfUpdate;
	}

	public String getPhoneLastUpdate(int index) {
		return (String) phoneLastUpdate.get(index);
	}

	public List getPhoneLastUpdateList() {
		return phoneLastUpdate;
	}

	public void setPhoneLastUpdate(int index, String phoneLastUpdate) {
		setElement(this.phoneLastUpdate, index, phoneLastUpdate);
	}

	public void setPhoneLastUpdateList(List phoneLastUpdate) {
		this.phoneLastUpdate = phoneSourceOfUpdate;
	}

	public String getEmailId(int index) {
		return (String) emailId.get(index);
	}

	public List getEmailIdList() {
		return emailId;
	}

	public void setEmailId(int index, String emailId) {
		setElement(this.emailId, index, emailId);
	}

	public void setEmailIdList(List emailId) {
		this.emailId = emailId;
	}

	public String getEmailType(int index) {
		return (String) emailType.get(index);
	}

	public List getEmailTypeList() {
		return emailType;
	}

	public void setEmailType(int index, String emailType) {
		setElement(this.emailType, index, emailType);
	}

	public void setEmailTypeList(List emailType) {
		this.emailType = emailType;
	}

	public String getEmailAddress(int index) {
		return (String) emailAddress.get(index);
	}

	public List getEmailAddressList() {
		return emailAddress;
	}

	public void setEmailAddress(int index, String emailAddress) {
		setElement(this.emailAddress, index, emailAddress);
	}

	public void setEmailNumberList(List emailAddress) {
		this.emailAddress = emailAddress;
	}

	public String getEmailSourceOfUpdate(int index) {
		return (String) emailSourceOfUpdate.get(index);
	}

	public List getEmailSourceOfUpdateList() {
		return emailSourceOfUpdate;
	}

	public void setEmailSourceOfUpdate(int index, String emailSourceOfUpdate) {
		setElement(this.emailSourceOfUpdate, index, emailSourceOfUpdate);
	}

	public void setEmailSourceOfUpdateList(List emailSourceOfUpdate) {
		this.emailSourceOfUpdate = emailSourceOfUpdate;
	}

	public String getEmailSiteOfUpdate(int index) {
		return (String) emailSiteOfUpdate.get(index);
	}

	public List getEmailSiteOfUpdateList() {
		return emailSiteOfUpdate;
	}

	public void setEmailSiteOfUpdate(int index, String emailSiteOfUpdate) {
		setElement(this.emailSiteOfUpdate, index, emailSiteOfUpdate);
	}

	public void setEmailSiteOfUpdateList(List emailSiteOfUpdate) {
		this.emailSiteOfUpdate = emailSourceOfUpdate;
	}

	public String getEmailLastUpdate(int index) {
		return (String) emailLastUpdate.get(index);
	}

	public List getEmailLastUpdateList() {
		return emailLastUpdate;
	}

	public void setEmailLastUpdate(int index, String emailLastUpdate) {
		setElement(this.emailLastUpdate, index, emailLastUpdate);
	}

	public void setEmailLastUpdateList(List emailLastUpdate) {
		this.emailLastUpdate = emailSourceOfUpdate;
	}

	public Date getPermAddrStartDate() {
		return permAddrStartDate;
	}

	public void setPermAddrStartDate(Date permAddrStartDate) {
		this.permAddrStartDate = permAddrStartDate;
	}

	public Date getPermAddrEndDate() {
		return permAddrEndDate;
	}

	public void setPermAddrEndDate(Date permAddrEndDate) {
		this.permAddrEndDate = permAddrEndDate;
	}

	public boolean isNoPhoneData() {
		if ((phoneId == null) || (phoneId.size() == 0)) {
			return true;
		} else {
			return false;
		}
	}

	public boolean isNoEmailData() {
		if ((emailId == null) || (emailId.size() == 0)) {
			return true;
		} else {
			return false;
		}
	}

	public boolean isPermAddrCurrent() {
		return permAddrCurrent;
	}

	public boolean isConfAddrCurrent() {
		return confAddrCurrent;
	}

	public boolean isTempAddrCurrent() {
		return tempAddrCurrent;
	}

	public String getPermAddrLastUpdate() {
		return permAddrLastUpdate;
	}

	public void setPermAddrLastUpdate(String permAddrLastUpdate) {
		this.permAddrLastUpdate = permAddrLastUpdate;
	}

	public String getPermAddrSourceOfUpdate() {
		return permAddrSourceOfUpdate;
	}

	public void setPermAddrSourceOfUpdate(String permAddrSourceOfUpdate) {
		this.permAddrSourceOfUpdate = permAddrSourceOfUpdate;
	}

	public String getPermAddrSiteOfUpdate() {
		return permAddrSiteOfUpdate;
	}

	public void setPermAddrSiteOfUpdate(String permAddrSiteOfUpdate) {
		this.permAddrSiteOfUpdate = permAddrSiteOfUpdate;
	}

	public String getPermBadAddressReason() {
		return permBadAddressReason;
	}

	public void setPermBadAddressReason(String permBadAddressReason) {
		this.permBadAddressReason = permBadAddressReason;
	}

	public void setPermAddrCurrent(boolean permAddrCurrent) {
		this.permAddrCurrent = permAddrCurrent;
	}

	public void setConfAddrCurrent(boolean confAddrCurrent) {
		this.confAddrCurrent = confAddrCurrent;
	}

	public void setTempAddrCurrent(boolean tempAddrCurrent) {
		this.tempAddrCurrent = tempAddrCurrent;
	}

	public boolean isConfAddrInFuture() {
		return confAddrInFuture;
	}

	public void setConfAddrInFuture(boolean confAddrInFuture) {
		this.confAddrInFuture = confAddrInFuture;
	}

	public boolean isPermAddrInFuture() {
		return permAddrInFuture;
	}

	public void setPermAddrInFuture(boolean permAddrInFuture) {
		this.permAddrInFuture = permAddrInFuture;
	}

	public boolean isTempAddrInFuture() {
		return tempAddrInFuture;
	}

	public void setTempAddrInFuture(boolean tempAddrInFuture) {
		this.tempAddrInFuture = tempAddrInFuture;
	}

	public boolean isConfAddrInPast() {
		return confAddrInPast;
	}

	public void setConfAddrInPast(boolean confAddrInPast) {
		this.confAddrInPast = confAddrInPast;
	}

	public boolean isPermAddrInPast() {
		return permAddrInPast;
	}

	public void setPermAddrInPast(boolean permAddrInPast) {
		this.permAddrInPast = permAddrInPast;
	}

	public boolean isTempAddrInPast() {
		return tempAddrInPast;
	}

	public void setTempAddrInPast(boolean tempAddrInPast) {
		this.tempAddrInPast = tempAddrInPast;
	}

	public boolean isTempAddrPresent() {
		return tempAddrPresent;
	}

	public void setTempAddrPresent(boolean tempAddrPresent) {
		this.tempAddrPresent = tempAddrPresent;
	}

	public boolean isConfAddrPresent() {
		return confAddrPresent;
	}

	public void setConfAddrPresent(boolean confAddrPresent) {
		this.confAddrPresent = confAddrPresent;
	}

	/**
	 * Validate the array type fields that can not be validated declaratively
	 * Validates phoneType and Phone Number
	 */
	public ActionMessages validateForm(ActionMapping mapping, HttpServletRequest request) {
		// Get the list of existing messages
		MessageResources messageResources = getResources(request);
		ActionMessages messages = getActionMessages(request);

		String labelPhoneType = messageResources.getMessage(PHONE_NUMBER_LABEL) + " "
				+ messageResources.getMessage(TYPE_LABEL);

		String labelPhoneNumber = messageResources.getMessage(PHONE_NUMBER_LABEL) + " "
				+ messageResources.getMessage(NUMBER_LABEL);

		String labelEmailType = messageResources.getMessage(EMAIL_ADDRESS_LABEL) + " "
				+ messageResources.getMessage(TYPE_LABEL);

		List phones = getPhoneTypeList();
		

		// not null C or CNF
		// convert to a date using Calendar object
		if (addressType.equalsIgnoreCase(UIConstants.TEMPORARY_ADDRESS_TYPE) || addressType.equalsIgnoreCase(UIConstants.CONFIDENTIAL_ADDRESS_TYPE)) {
			
				if (startDate == null)
				{
					if ((endDate != null) && (endDate.trim().length()>0))
					{
						messages.add("startDate",
								new ActionMessage(MessageKeys.ERRORS_INVALID_EMPTY_DATE,"StartDate"));
					}
				}
				if ((startDate != null) && (startDate.trim().length() == 0))
				{
					if ((endDate != null) && (endDate.trim().length()>0))
					{
						messages.add("startDate",
								new ActionMessage(MessageKeys.ERRORS_INVALID_EMPTY_DATE,"StartDate"));
					}
				}
				if ((startDate != null) && (startDate.trim().length() > 0))
				{
						
					if (endDate == null)
					{
						messages.add("endDate",
								new ActionMessage(MessageKeys.ERRORS_INVALID_EMPTY_DATE,"EndDate"));
				
					}
					if (endDate.trim().length()==0)
					{
						messages.add("endDate",
								new ActionMessage(MessageKeys.ERRORS_INVALID_EMPTY_DATE,"EndDate"));
					
					}
				}
				if (startDate != null && !"".equals(startDate.trim()) && endDate != null && !"".equals(endDate.trim()) ) {
				// getting date Object from string
				Date startDateObj = getDateFromString(startDate, messages);
				Date endDateObj = getDateFromString(endDate, messages);
				
				// checking End Date is NOT before the Start Date
				if (!startDateObj.before(endDateObj)) {
					messages.add("startDate",
							new ActionMessage(MessageKeys.ERRORS_INVALID_BEFORE_DATE, "StartDate", "EndDate"));
				}
				
				if(addressType.equalsIgnoreCase(UIConstants.CONFIDENTIAL_ADDRESS_TYPE) && (this.selectedConfAddrCategories==null || this.selectedConfAddrCategories.length<=0)){
					messages.add("Confidential Address",
							new ActionMessage(MessageKeys.ERRORS_CONF_ADDRESS_CATEGORY_REQUIRED));
				}

				}
			 /*else {
				messages.add("startDate", new ActionMessage(MessageKeys.ERRORS_INVALID_FURUTE_DATE, endDate, endDate));
			}*/
		}

		for (int i = 0; i < phones.size(); i++) {
			// If phone number is empty, we will delete this row so no other
			// validation is necessary
			if (StringUtils.isNotEmpty(getPhoneNumber(i))) {
				// CCR12146
				if (getPhoneNumber(i).length() > MAX_PHONE_NUMBER_LENGTH) {
					messages.add("phoneNumber", new ActionMessage(MessageKeys.ERRORS_MAXLENGTH, labelPhoneNumber,
							new Integer(MAX_PHONE_NUMBER_LENGTH).toString()));
				}
				if (StringUtils.isEmpty(getPhoneType(i))) {
					messages.add("phoneType",
							new ActionMessage(MessageKeys.ERRORS_REQUIRED, labelPhoneType + " " + (i + 1)));
				}
			}
		}

		List emails = getEmailTypeList();
		for (int i = 0; i < emails.size(); i++) {
			// If email is empty, we will delete this row so no other validation
			// is necessary
			if (StringUtils.isNotEmpty(getEmailAddress(i))) {
				if (StringUtils.isEmpty(getEmailType(i))) {
					messages.add("emailType",
							new ActionMessage(MessageKeys.ERRORS_REQUIRED, labelEmailType + " " + (i + 1)));
				}
			}
		}
		// when update and addressType is C or T
		if (addressType.equalsIgnoreCase("c")) {

		}

		return messages;
	}

	/*
	 * This will convert the string in format("MM/dd/yyyy") to a DateObject. On
	 * failure it will return Action Error Message.
	 * 
	 * @param dateString
	 * 
	 * @param msg
	 * 
	 * @return Date
	 */
	private Date getDateFromString(String dateString, ActionMessages msg) {
		
		Date newDate = null;
		
		if(dateString != null){
		
			SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
		
		try {
			newDate = sdf.parse(dateString);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			msg.add("startDate", new ActionMessage(MessageKeys.ERRORS_INVALID_IMPRECISE_DATE, dateString, dateString));
		}
		}

		return newDate;
	}

	public List getConfAddrCategories() {
		return confAddrCategories;
	}

	public void setConfAddrCategories(List confAddrCategories) {
		this.confAddrCategories = confAddrCategories;
	}

	public String getFormattedConfAddrCategories() {
		return confAddrCategories == null ? "" : JspUtils.displayValues(confAddrCategories, "", null);
	}

	public String getAddressType() {
		return addressType;
	}

	public void setAddressType(String addressType) {
		this.addressType = addressType;
	}

	public String getStartDate() {
		return startDate;
	}

	public void setStartDate(String startDate) {
		this.startDate = startDate;
	}

	public String getEndDate() {
		return endDate;
	}

	public void setEndDate(String endDate) {
		this.endDate = endDate;
	}

	public String[] getSelectedConfAddrCategories() {
		return selectedConfAddrCategories;
	}

	public void setSelectedConfAddrCategories(String[] selectedConfAddrCategories) {
		this.selectedConfAddrCategories = selectedConfAddrCategories;
	}
}
