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

// Java classes
import java.util.Date;
import javax.servlet.http.HttpServletRequest;

// Library classes
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.util.MessageResources;

// ESR classes
import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.infra.ImpreciseDateUtils;
import gov.va.med.esr.ui.ApplicationConstants.MessageKeys;
import gov.va.med.esr.ui.common.util.DateUtils;
import gov.va.med.fw.util.StringUtils;

/**
 * Perform programatic validation for all the registry edit actions.
 * @author Muddaiah Ranga
 * @version 3.0
 */
public class RegistryValidator implements RegistryConstants {

    /**
     * Validates the registry information.
     * 
     * @param form the military service form.
     * @param request the request object.
     * 
     * @return the action messages.
     */
    protected static ActionErrors validate(RegistryInfoForm form, 
                                           HttpServletRequest request,
                                           ActionErrors errors) {
        if(errors == null) errors =  new ActionErrors();
        if(form instanceof RegistryPHInfoForm) {
            errors = validatePHInfo((RegistryPHInfoForm)form,request,errors);
        } if(form instanceof RegistryPOWInfoForm) {
            errors = validatePOWInfo((RegistryPOWInfoForm)form,request,errors);
        } if(form instanceof RegistrySHADInfoForm) {
            errors = validateSHADInfo((RegistrySHADInfoForm)form,request,errors);
        }
        return errors;
    }
        
    private static ActionErrors validatePHInfo(RegistryPHInfoForm form, HttpServletRequest request, ActionErrors valErrors) {
        ActionErrors errors =  new ActionErrors();
        MessageResources messageResources = form.getResources(request);
        errors.add(valErrors);
        for(int i=0; i<form.getDocumentCount(); i++) {
            validatePHDocument(form,i,errors,messageResources);
        }
        return errors;
    }
    
    private static ActionErrors validatePOWInfo(RegistryPOWInfoForm form, HttpServletRequest request, ActionErrors valErrors) {
        ActionErrors errors =  new ActionErrors();
        MessageResources messageResources = form.getResources(request);
        errors.add(valErrors);
        for(int i=0; i<form.getEpisodeCount(); i++) {
            validatePOWEpisode(form,i,errors,messageResources);
        }
        
//        String dateEntered = form.getDateEntered();
//        String label = messageResources.getMessage(LABEL_DATE_ENTERED);
//        String fieldName = "dateEntered";
//        if(StringUtils.isEmpty(dateEntered)) {
//            errors.add(fieldName,new ActionMessage(MessageKeys.ERRORS_REQUIRED,label));
//        } else {
//            validateDate(dateEntered,fieldName,label,errors);
//        }
        
        return errors;
    }
    
    private static ActionErrors validateSHADInfo(RegistrySHADInfoForm form, HttpServletRequest request, ActionErrors valErrors) {
        ActionErrors errors =  new ActionErrors();
        MessageResources messageResources = form.getResources(request);
        errors.add(valErrors);
        for(int i=0; i<form.getDocumentCount(); i++) {
            validateSHADDocument(form,i,errors,messageResources);
        }
        return errors;
    }
    
    private static ActionErrors validatePHDocument(RegistryPHInfoForm form,
                                                   int documentIndex,
                                                   ActionErrors errors,
                                                   MessageResources messageResources) {
        if(!form.isPHDocumentEmpty(documentIndex)) {
            String index = "[" + documentIndex + "]";
            String label = null;
            String fieldName = null;
            String documentType = form.getDocumentType(documentIndex);
            if(StringUtils.isEmpty(documentType)) {
                label = messageResources.getMessage(LABEL_REGISTRY_DOCUMENT_TYPE);
                errors.add("documentType" + index,new ActionMessage(MessageKeys.ERRORS_REQUIRED,label));
            }

            String dataSource = form.getDataSource(documentIndex);
            if(StringUtils.isEmpty(dataSource)) {
                label = messageResources.getMessage(LABEL_REGISTRY_DATA_SOURCE);
                fieldName = "dataSource" + index;
                errors.add(fieldName,new ActionMessage(MessageKeys.ERRORS_REQUIRED,label));
            }
            
            String documentReceivedDate = form.getDocumentReceivedDate(documentIndex);
            if(StringUtils.isNotEmpty(documentReceivedDate)) {
                label = messageResources.getMessage(LABEL_REGISTRY_DOCUMENT_RECEIVED_DATE);
                fieldName = "documentReceivedDate" + index;
                validateDate(documentReceivedDate,fieldName,label,errors);
            }
            
            String documentAcceptable = form.getDocumentAcceptable(documentIndex);
            if(StringUtils.isEmpty(documentAcceptable)) {
                label = messageResources.getMessage(LABEL_REGISTRY_DOCUMENT_ACCEPTABLE);
                fieldName = "documentAcceptable" + index;
                errors.add(fieldName,new ActionMessage(MessageKeys.ERRORS_REQUIRED,label));
            }
            
            String unacceptableRemark = form.getUnacceptableRemark(documentIndex);
            if(StringUtils.isNotEmpty(unacceptableRemark) && unacceptableRemark.length() > 200) {
                label = messageResources.getMessage(LABEL_REGISTRY_DOCUMENT_UNACCEPTABLE_REMARK);
                fieldName = "unacceptableRemark" + index;
                errors.add(fieldName,new ActionMessage(ERROR_UNACCEPTABLE_REMARK_INVALID_LENGTH,label));
            }
        }
        return errors;
    }
    
    private static ActionErrors validatePOWEpisode(RegistryPOWInfoForm form,
                                                   int documentIndex,
                                                   ActionErrors errors,
                                                   MessageResources messageResources) {
        if(!form.isPOWEpisodeEmpty(documentIndex)) {
            String index = "[" + documentIndex + "]";
            String label = null;
            String fieldName = null;

            String dataSource = form.getDataSource(documentIndex);
            if(StringUtils.isEmpty(dataSource)) {
                label = messageResources.getMessage(LABEL_POW_DATA_SOURCE);
                fieldName = "dataSource" + index;
                errors.add(fieldName,new ActionMessage(MessageKeys.ERRORS_REQUIRED,label));
            }

            boolean captureDateValid = false;
            String captureDate = form.getPowCaptureDate(documentIndex);
            String captureDateLabel = messageResources.getMessage(LABEL_POW_CAPTURE_DATE);
            String captureDateFieldName = "powCaptureDate" + index;
            if(StringUtils.isEmpty(captureDate)) {
                errors.add(captureDateFieldName,new ActionMessage(MessageKeys.ERRORS_REQUIRED,captureDateLabel));
            } else {
                captureDateValid = validateImpreciseDate(captureDate,captureDateFieldName,captureDateLabel,errors);
            }

            boolean releaseDateValid = false;
            String releaseDate = form.getPowReleaseDate(documentIndex);
            String releaseDateLabel = messageResources.getMessage(LABEL_POW_RELEASE_DATE);
            String releaseDateFieldName = "powReleaseDate" + index;
            if(StringUtils.isEmpty(releaseDate)) {
                errors.add(releaseDateFieldName,new ActionMessage(MessageKeys.ERRORS_REQUIRED,releaseDateLabel));
            } else {
                releaseDateValid = validateImpreciseDate(releaseDate,releaseDateFieldName,releaseDateLabel,errors);
            }
            
            if(captureDateValid && releaseDateValid) {
                Date captureDatePrecise = ImpreciseDateUtils.getDateWithDefault(DateUtils.getImpreciseDate(captureDate));
                Date releaseDatePrecise = ImpreciseDateUtils.getDateWithDefault(DateUtils.getImpreciseDate(releaseDate));
                if(captureDatePrecise.after(releaseDatePrecise)) {
                    ActionMessage message = new ActionMessage(LABEL_DATES_INVALID,captureDateLabel,releaseDateLabel);
                    errors.add(captureDateFieldName,message);
                    errors.add(releaseDateFieldName,message);
                }
            }
            
            String confinementLocation = form.getConfinementLocation(documentIndex);
            if(StringUtils.isEmpty(confinementLocation)) {
                label = messageResources.getMessage(LABEL_POW_CONFINEMENT_LOCATION);
                fieldName = "confinementLocation" + index;
                errors.add(fieldName,new ActionMessage(MessageKeys.ERRORS_REQUIRED,label));
            }
        }
        return errors;
    }
    
    private static ActionErrors validateSHADDocument(RegistrySHADInfoForm form,
                                                     int documentIndex,
                                                     ActionErrors errors,
                                                     MessageResources messageResources) {
        if(!form.isSHADDocumentEmpty(documentIndex)) {
            String index = "[" + documentIndex + "]";
            String label = null;
            String fieldName = null;
            
            String documentType = form.getDocumentType(documentIndex);
            if(StringUtils.isEmpty(documentType)) {
                label = messageResources.getMessage(LABEL_REGISTRY_DOCUMENT_TYPE);
                errors.add("documentType" + index,new ActionMessage(MessageKeys.ERRORS_REQUIRED,label));
            }

            String documentReceivedDate = form.getDocumentReceivedDate(documentIndex);
            if(StringUtils.isNotEmpty(documentReceivedDate)) {
                label = messageResources.getMessage(LABEL_REGISTRY_DOCUMENT_RECEIVED_DATE);
                fieldName = "documentReceivedDate" + index;
                validateDate(documentReceivedDate,fieldName,label,errors);
            }
        }
        return errors;
    }
    
    /**
     * Validate the date for the correct format and future date check.
     * 
     * @param fieldValue the date field value
     * @param fieldName the field name
     * @param fieldLabel field label
     * @param errors the validation error object
     */
    private static boolean validateDate(String fieldValue,String fieldName,String fieldLabel,ActionErrors errors) {
        if(StringUtils.isNotEmpty(fieldValue)) {
            try {
                Date date = DateUtils.getDate(fieldValue);
                Date currentDate = new Date();
                if(date.after(currentDate)) {
                    errors.add(fieldName,new ActionMessage(ERROR_DATE_NO_FUTURE,fieldLabel));
                    return false;
                }
            } catch (Exception ex) {
                errors.add(fieldName,new ActionMessage(MessageKeys.ERRORS_INVALID,fieldLabel));
                return false;
            }
        }
        return true;
    }
    
    /**
     * Validate the imprecise date for the correct format and future date check.
     * 
     * @param fieldValue the date field value
     * @param fieldName the field name
     * @param fieldLabel field label
     * @param errors the validation error object
     */
    private static boolean validateImpreciseDate(String fieldValue,String fieldName,String fieldLabel,ActionErrors errors) {
        if(StringUtils.isNotEmpty(fieldValue)) {
            try {
                ImpreciseDate impDate = DateUtils.getImpreciseDate(fieldValue);
                Date date = ImpreciseDateUtils.getDateWithDefault(impDate);
                if(date.after(new Date())) {
                    errors.add(fieldName,new ActionMessage(ERROR_DATE_NO_FUTURE,fieldLabel));
                    return false;
                }
            } catch (Exception ex) {
                errors.add(fieldName,new ActionMessage(MessageKeys.ERRORS_INVALID_IMPRECISE_DATE,fieldLabel));
                return false;
            }
        }
        return true;
    }
}
