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

// Java classes
import java.util.Iterator;

import java.util.Set;

//Library classes
import org.apache.commons.lang.Validate;

//Framework classes
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.validation.ValidationMessages;
import gov.va.med.fw.validation.ValidationServiceException;

// EDB classes
import gov.va.med.esr.common.model.ee.Document;
import gov.va.med.esr.common.model.ee.PrisonerOfWar;
import gov.va.med.esr.common.model.ee.PurpleHeart;
import gov.va.med.esr.common.model.ee.SHAD;
import gov.va.med.esr.common.model.lookup.RegistryType;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.registry.Registry;
import gov.va.med.esr.common.rule.data.RegistryInputData;
import gov.va.med.esr.common.rule.service.RegistryRuleService;
import gov.va.med.esr.common.rule.service.RuleValidationService;
import gov.va.med.esr.service.LoadRegistryResult;


/**
 * Registry rule service implementation.
 * 
 * @author Muddaiah Ranga
 * @version 3.0
 */
public class RegistryRuleServiceImpl extends AbstractRuleValidationServiceAwareImpl implements RegistryRuleService {

    private static final long serialVersionUID = 3584313719227829932L;
    
    private String manageRegistryRuleParameters = null;
    
    private String loadRegistryFilesRuleParameters = null;  
    
    private String linkPersonRegistryRuleParameters = null;

	public RegistryRuleServiceImpl() {
      super();
	}
   
	/* (non-Javadoc)
	 * @see gov.va.med.esr.common.rule.service.RegistryRuleService#manageRegistry(gov.va.med.esr.common.model.registry.Registry, gov.va.med.esr.common.model.registry.Registry)
	 */
	public Registry manageRegistry(Registry incoming, Registry onFile) throws ServiceException {
        Validate.notNull(incoming, "A registry must not be null for validation");
        
        // Perform validation
        this.doValidation(incoming);
        
        Registry pristineRegistry = (Registry)onFile.clone();
        RegistryType regTYpe=incoming.getRegistryTrait()!=null?incoming.getRegistryTrait().getRegistryType():null;
        // Updates the registry
        this.invokeRuleFlow(this.getRuleParameters(getManageRegistryRuleParameters()),new RegistryInputData(incoming,onFile,pristineRegistry,true,regTYpe ) );

	    return onFile;
	}

    /**
     * @see gov.va.med.esr.common.rule.service.RegistryRuleService#processRegistry(gov.va.med.esr.common.model.registry.Registry, gov.va.med.esr.common.model.registry.Registry, gov.va.med.esr.service.LoadRegistryResult)
     */
    public Registry processRegistry(Registry incoming, Registry onFile, LoadRegistryResult result) throws ServiceException {
        Validate.notNull(incoming, "A registry must not be null for validation");
        
        Registry pristineRegistry = (Registry)onFile.clone();
        RegistryType regTYpe=incoming.getRegistryTrait()!=null?incoming.getRegistryTrait().getRegistryType():null;
        RegistryInputData data = new RegistryInputData(incoming, onFile, pristineRegistry, false,regTYpe);
        data.setAmbiguousMatch(result.isAmbiguousMatch());
        data.setExactMatchDifferentEpisode(result.isExactMatchDifferentEpisode());
        data.setExactMatchSameEpisode(result.isExactMatchSameEpisode());
        data.setLoadRegistryResult(result);
        data.setExactMatch(result.isExactMatch());

        // Updates the registry
        this.invokeRuleFlow( this.getRuleParameters( getLoadRegistryFilesRuleParameters() ), data);

        return onFile;
    }    
     
    /* 
     * @see gov.va.med.esr.common.rule.service.RegistryRuleService#linkPersonRegistries(gov.va.med.esr.common.model.registry.Registry, gov.va.med.esr.common.model.registry.Registry, java.util.Set, gov.va.med.esr.common.model.registry.Registry)
     */
    public void linkPersonRegistry(Registry incoming, Registry onFile, Person incomingPerson, Person onFilePerson,RegistryType registryType, boolean isFromUI)
    throws ServiceException
    {
    	 Validate.notNull(onFilePerson, "A person must not be null for validation");
    	 Registry pristine = onFile!=null?(Registry)onFile.clone():null;
         RegistryInputData inputData = new RegistryInputData(incoming,onFile,pristine,incomingPerson,onFilePerson,registryType,isFromUI);
         this.invokeRuleFlow(this.getRuleParameters(this.getLinkPersonRegistryRuleParameters()),inputData);
    } 
    
    // ************************************** Private Methods ************************************ //

    private void doValidation(Registry registry) throws ServiceException {
        ValidationMessages messages = new ValidationMessages();
        
        // Validate the common registry fields first
        RuleValidationService ruleService = this.getRuleValidationService();
        ValidationMessages errors = ruleService.validateRegistry(registry,true);
        if( errors != null && !errors.isEmpty() ) {
            messages.add(errors); 
        }
        
        // Validate documents/episodes experience
        Set docs = this.getDocuments(registry);
        if(docs != null) {
            for(Iterator iter=docs.iterator(); iter.hasNext(); ) {             
                Document doc = (Document)iter.next();
                errors = ruleService.validateRegistryDocument(registry,doc,true);
                if( errors != null && !errors.isEmpty() ) {
                    messages.add( errors,String.valueOf(doc.hashCode()) ); 
                }
            }
        }
        if( messages != null && !messages.isEmpty() ) {
            throw new ValidationServiceException( messages ); 
        }
    }
    
    private Set getDocuments(Registry registry) {
        RegistryType registryType = registry.getRegistryTrait().getRegistryType();
        Set docs = null;
        if(registryType.isPurpleHeart()) {
            docs = ((PurpleHeart)registry).getDocuments();
        } else if(registryType.isPrisonerOfWar()) {
            docs = ((PrisonerOfWar)registry).getEpisodes();
        } else if(registryType.isSHAD()) {
            docs = ((SHAD)registry).getDocuments();
        }
        return docs;
    }
    
    public String getManageRegistryRuleParameters() {
        return manageRegistryRuleParameters;
    }

    public void setManageRegistryRuleParameters(String manageRegistryRuleParameters) {
        this.manageRegistryRuleParameters = manageRegistryRuleParameters;
    }

    /**
     * @return Returns the loadRegistryFilesRuleParameters.
     */
    public String getLoadRegistryFilesRuleParameters() {
        return loadRegistryFilesRuleParameters;
    }

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

    public String getLinkPersonRegistryRuleParameters() {
        return linkPersonRegistryRuleParameters;
    }

    public void setLinkPersonRegistryRuleParameters(
            String linkPersonRegistryRuleParameters) {
        this.linkPersonRegistryRuleParameters = linkPersonRegistryRuleParameters;
    }

    public void afterPropertiesSet() throws Exception {
        super.afterPropertiesSet();
        Validate.notNull( this.manageRegistryRuleParameters, "Manage registry parameters must not be null");
        Validate.notNull( this.loadRegistryFilesRuleParameters, "Load registry files parameters must not be null");        
    }
}