/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.esr.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Iterator;

import gov.va.med.fw.persistent.DAOException;
import gov.va.med.fw.rule.RuleException;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.util.DateUtils;
import gov.va.med.fw.util.StringUtils;
import gov.va.med.fw.util.builder.BuilderException;

import gov.va.med.esr.common.builder.entity.BooleanBuilder;
import gov.va.med.esr.common.model.system.SystemParameter;
import gov.va.med.esr.common.persistent.system.SystemParameterDAO;

import gov.va.med.esr.service.SystemParameterService;

public class SystemParameterServiceImpl extends AbstractRuleAwareServiceImpl implements SystemParameterService{

    private SystemParameterDAO systemParameterDAO = null;

    private String esrVersion = "Undefined";
    private String defaultEsrImplementationDate = "01/01/2007";

    public SystemParameterServiceImpl() {
        super();
    }

    public List findAll() throws ServiceException {
        try {
            return getSystemParameterDAO().findAll();
        } catch (DAOException e) {
            throw new ServiceException("Can not retrive System Parameters",e);
        }
    }

    public SystemParameter getByName(String parameterName) throws ServiceException {
        try {
            return getSystemParameterDAO().getByName(parameterName);
        } catch (DAOException e) {
            throw new ServiceException("Can not retrive System Parameter " + parameterName,e);
        }
    }

    public Set save(Set parameters) throws ServiceException {

        boolean AOTreatmentAuthorityExpired = false;
        boolean ECTreatmentAuthorityExpired = false;

        try {
            List onFileSystemParameters = findAll();

            // Ensure that something changed on the entities as compared to the onFile entities
            ensureEntityChanged(parameters, onFileSystemParameters);

            Map onFileMap = new HashMap ();
            Set onFileSet = new HashSet();
            for (Iterator iterator = onFileSystemParameters.iterator(); iterator.hasNext();)
            {
                SystemParameter systemParameter = (SystemParameter)iterator.next();
                onFileMap.put(systemParameter.getName(), systemParameter);
                onFileSet.add(systemParameter);
            }

            for (Iterator iterator = parameters.iterator(); iterator.hasNext();)
            {
                SystemParameter incoming = (SystemParameter)iterator.next();
                SystemParameter onFile = (SystemParameter) onFileMap.get(incoming.getName());

                // CCR9936 (ref.CCR8753)
                // A/O and SW Asia Special Treatment Authority Indicator
                // When this value is changed from “Y” to “N” the Agent Orange Special Treatment Authority Expiration Date is set to the current date.
                if (incoming.getName().equals(SystemParameter.AO_TREATMENT_AUTHORITY_IND)) {
                  if (Boolean.FALSE.equals(getBoolean(incoming.getValue())) &&
                      Boolean.TRUE.equals(getBoolean(onFile.getValue()))) {
                    AOTreatmentAuthorityExpired = true;
                  }
                }

                if (incoming.getName().equals(SystemParameter.SWAC_TREATMENT_AUTHORITY_IND)) {
                  if (Boolean.FALSE.equals(getBoolean(incoming.getValue())) &&
                      Boolean.TRUE.equals(getBoolean(onFile.getValue()))) {
                    ECTreatmentAuthorityExpired = true;
                  }
                }

                merge(incoming, onFile);
           }

            setExpirationDate(onFileMap, SystemParameter.AO_TREATMENT_AUTHORITY_EXP_DATE, AOTreatmentAuthorityExpired);
            setExpirationDate(onFileMap, SystemParameter.SWAC_TREATMENT_AUTHORITY_EXP_DATE, ECTreatmentAuthorityExpired);

           return getSystemParameterDAO().update(onFileSet);
        } catch (DAOException e) {
            throw new ServiceException("Can not update System Parameters ",e);
        }
    }

    public SystemParameterDAO getSystemParameterDAO() {
        return systemParameterDAO;
    }

    public void setSystemParameterDAO(SystemParameterDAO systemParameterDAO) {
        this.systemParameterDAO = systemParameterDAO;
    }

    public String getEsrVersion() throws ServiceException
    {
        return this.esrVersion;
    }

    public void setEsrVersion(String esrVersion)
    {
        this.esrVersion = esrVersion;
    }

    public void setDefaultEsrImplementationDate(String value) throws ServiceException
    {
        if (StringUtils.isNotEmpty(value)){
            defaultEsrImplementationDate = value;
        }
    }

    protected Date getDateParameter(String paramName) throws ServiceException
    {
        return getDateParameter(paramName, null);
    }

    protected Date getDateParameter(String paramName, String defaultDateStr) throws ServiceException
    {
        Date dateParam = null;

        String dateStr = defaultDateStr;
        SystemParameter par = getByName(paramName);

        if (par != null && StringUtils.isNotEmpty((par.getValue().trim()))) {
            //CCR 9677: the empty value of ao and swa special treatment auth exp date is ' ' (one space)
        	// because the db not-null constrain. trim it!
        	dateStr = par.getValue().trim();
        }

        if (dateStr != null) {
            try {
                String[] dateFormats = {DateUtils.MMDDYYYY}; //NOTE: MMDDYYY her is MM/dd/yyyy in Java!
                dateParam = DateUtils.parseDate(dateStr,dateFormats);
            }
            catch (Exception e){
                throw new ServiceException("Unable to parse " + paramName + " from " + dateStr ,e);
           }
        }

        return dateParam;
    }

    protected Boolean getBooleanParameter(String paramName) throws ServiceException {
        Boolean boolParam = null;

        SystemParameter parameter = getByName(paramName);

        if (parameter != null) {
            boolParam = getBoolean(parameter.getValue());
        }
        return boolParam;
    }

    protected Boolean getBoolean(String paramValue) throws ServiceException{
      Boolean boolParam = null;

      if (paramValue != null) {
        try {
          boolParam = (new BooleanBuilder()).build(paramValue);
        }  catch (BuilderException eb) {
          throw new ServiceException("Unable to parse parameter value " + paramValue + ".", eb);
      }
     }
      return boolParam;

    }

    public Date getEsrImplementationDate() throws ServiceException
    {
        return getDateParameter(SystemParameter.ESR_IMPLEMENTATION_DATE, defaultEsrImplementationDate);
    }

    /*
     *  Agent Orange Special Treatment Authority Indicator
     */
    public Boolean getAOTreatmentAuthorityIndicator() throws ServiceException {
        return getBooleanParameter(SystemParameter.AO_TREATMENT_AUTHORITY_IND);
    }

    /*
     * SW Asia Conditions Special Treatment Authority Indicator
    */
    public Boolean getECTreamentAuthorityIndicator() throws ServiceException {
        return getBooleanParameter(SystemParameter.SWAC_TREATMENT_AUTHORITY_IND);
    }

    /*
     *  Agent Orange Special Treatment Authority Expiration Date
     */
    public Date getAOTreatmentAuthorityExpirationDate() throws ServiceException {
        return getDateParameter(SystemParameter.AO_TREATMENT_AUTHORITY_EXP_DATE);
    }

    /*
     * SW Asia Conditions Special Treatment Authority Expiration Date
     */
    public Date getECTreatmentAuthorityExpirationDate() throws ServiceException {
        return getDateParameter(SystemParameter.SWAC_TREATMENT_AUTHORITY_EXP_DATE);
    }

    /**
     * Util method to fetch Enrollment Reg Date from APP_PARAMETER table.
     *
     * @return enrollmentRegulation Date
     */
    public Date getEnrollmentRegulationDate() throws ServiceException
    {
        SystemParameter par = getByName(SystemParameter.ENROLLMENT_REGULATION_DATE);
        String dateStr = "";
        if (par != null && StringUtils.isNotEmpty(par.getValue())) {
            dateStr = par.getValue();
        }
        try{
            String[] dateFormats = {DateUtils.MMDDYYYY};
            Date regDate=DateUtils.parseDate(dateStr,dateFormats);
            return regDate;
        }catch (Exception e){
            throw new ServiceException("Unable to parse Enrollment Regulation date from " + dateStr ,e);
       }
    }

    /**
     * Method to return the VFA Start Date from APP_PARAMETER table
     */
    public Date getVFAStartDate() throws ServiceException {
        SystemParameter par = getByName(SystemParameter.VFA_START_DATE);
        String dateStr = "";
        if (par != null && StringUtils.isNotEmpty(par.getValue())) {
            dateStr = par.getValue();
        }
        try{
            String[] dateFormats = {DateUtils.MMDDYYYY};
            Date regDate=DateUtils.parseDate(dateStr,dateFormats);
            return regDate;
        }catch (Exception e){
            throw new ServiceException("Unable to parse VFA Start Date from " + dateStr ,e);
       }
	}

	private void merge(SystemParameter incoming, SystemParameter onFile)
    {
        onFile.setValue(incoming.getValue());
        onFile.setUnit(incoming.getUnit());
    }

    // CCR9936 (ref.CCR8753)
    // A/O and SW Asia Special Treatment Authority Indicator
    // When this value is changed from “Y” to “N” the Agent Orange Special Treatment Authority Expiration Date is set to the current date.
    private void setExpirationDate(Map map, String paramType, boolean isExpired) {

      SystemParameter expDate = (SystemParameter) map.get(paramType);
      if (isExpired) {
        expDate.setValue(DateUtils.format(new Date(), DateUtils.MMDDYYYY));
      } else if (StringUtils.isEmpty(expDate.getValue())) {
        // The value column in DB is nut-null, so reset to " ".
        expDate.setValue(" ");
      }
    }

    public Boolean getVOAAnonymousLevel1ProcessIndicator() throws ServiceException {
        return getBooleanParameter(SystemParameter.VOA_ANONYMOUS_LEVEL1_PROCESS_INDICATOR);
    }

    public Boolean getMSDSServiceIndicator() throws ServiceException {
        return getBooleanParameter(SystemParameter.MSDS_SERVICE_INDICATOR);
    }

    public Boolean getMSDSReconIndicator() throws ServiceException{
    	return getBooleanParameter(SystemParameter.MSDS_RECON_INDICATOR);
    }
    /**
     * Util method to fetch DEFAULT_HANDBOOK_BATCH_RELEASE_CONTROL_NUMBER from APP_PARAMETER table.
     *
     * @return DEFAULT_HANDBOOK_BATCH_RELEASE_CONTROL_NUMBER value.
     */
    public String getHandBookReleaseCtl() throws ServiceException
    {
        SystemParameter par = getByName(SystemParameter.DEFAULT_HANDBOOK_BATCH_RELEASE_CONTROL_NUMBER);
       String releaseCtl=par.getValue();
      return releaseCtl;
    }
    public void updateDefaultHandBookReleaseCtl(String releaseCtl) throws ServiceException
    {
    	try{
        SystemParameter par = getByName(SystemParameter.DEFAULT_HANDBOOK_BATCH_RELEASE_CONTROL_NUMBER);
      par.setValue(releaseCtl);
      this.systemParameterDAO.saveObject(par);
    	}
    	catch (DAOException ex)
		{
			throw new ServiceException("Error updating handbook release control number " +  ex);
		}
    }

    /**
     * Util method to fetch HANDBOOK ROLL OUT OVER from APP_PARAMETER table.
     *
     * @return true or false.
     */
    public boolean isHandBookRollOutOver() throws ServiceException
    {
        SystemParameter par = getByName(SystemParameter.HANDBOOK_ROLL_OUT_OVER);
       String rollout=par.getValue();
       if("Y".equals(rollout))
    	   return true;
       else
    	   return false;

    }

    public Boolean getVBADataSharingIndicator() throws ServiceException{
    	return getBooleanParameter(SystemParameter.VBA_DATA_SHARING_INDICATOR);
    }
    //CCR12064
    public Boolean getHBPDataSharingIndicator() throws ServiceException{
    	return getBooleanParameter(SystemParameter.HBP_DATA_SHARING_INDICATOR);
    }

    // CodeCR12906
	public Boolean getIVMFinalLetterIndicator() throws ServiceException {
    	return getBooleanParameter(SystemParameter.IVM_FINAL_LETTER_INDICATOR);
	}

	// Determine if Self Identified Gender Identity is implemented
	public Boolean getEsSidIndicator() throws ServiceException {
	    return getBooleanParameter(SystemParameter.ES_SID_INDICATOR);
	}

	// Determine if MVI Date of Death Service Indicator is implemented
	public Boolean getDODIndicator() throws ServiceException {
	    return getBooleanParameter(SystemParameter.DOD_INDICATOR);
	}

	//CCR 13856
	public Boolean getDODSharing() throws ServiceException {
		return getBooleanParameter(SystemParameter.DOD_SHARING);
	}

	 /**
     * Util method to fetch CL_VISTA_FULL_ROLLOUT from APP_PARAMETER table.
     *
     * @return ALL-including CL data for all VistA sites, NONE-Not including CL data for all vistA sites
     * selected sites separated by comma delimiter- only including CL data for those selected sites
     */
    public String getCLVistARolloutStr() throws ServiceException
    {
        SystemParameter par = getByName(SystemParameter.CL_VISTA_ROLLOUT_INDICATOR);
        String clVistARollout=par.getValue();
      return clVistARollout;
    }
}
