/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.esr.common.validator.person;

// Java Classes

// Library Classes

// Framework Classes
import java.util.Iterator;

import gov.va.med.fw.persistent.DAOException;
import gov.va.med.fw.util.builder.Validator;
import gov.va.med.fw.util.builder.ValidatorException;

// Common Classes
import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.model.lookup.NameType;
import gov.va.med.esr.common.model.person.Name;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.persistent.lookup.LookupsDAO;
import gov.va.med.esr.common.validator.AbstractDQValidator;
import gov.va.med.esr.service.LookupService;
import gov.va.med.esr.service.UnknownLookupCodeException;
import gov.va.med.esr.service.UnknownLookupTypeException;

/**
 * @author Martin Francisco
 */
public class PersonDQValidator
    extends AbstractDQValidator
{
    private static final long serialVersionUID = -6137838653506200625L;
    
    private Validator birthRecordValidator;
    private Validator deathRecordValidator;
    private Validator nameValidator;

    private LookupService lookupService;

    public PersonDQValidator()
    {
        super();
    }

    public Validator getBirthRecordValidator()
    {
        return this.birthRecordValidator;
    }

    public void setBirthRecordValidator(Validator birthRecordValidator)
    {
        this.birthRecordValidator = birthRecordValidator;
    }

    public Validator getDeathRecordValidator()
    {
        return this.deathRecordValidator;
    }

    public void setDeathRecordValidator(Validator deathRecordValidator)
    {
        this.deathRecordValidator = deathRecordValidator;
    }

    public Validator getNameValidator()
    {
        return this.nameValidator;
    }

    public void setNameValidator(Validator nameValidator)
    {
        this.nameValidator = nameValidator;
    }

    public LookupService getLookupService()
    {
        return this.lookupService;
    }

    public void setLookupService(LookupService lookupService)
    {
        this.lookupService = lookupService;
    }

    private boolean containsNameType(Person input, NameType type)
        throws ValidatorException
    {
        for(Iterator i = input.getNames().iterator(); i.hasNext();)
        {
            Name name = (Name)i.next();
            if(type.equals(name.getType()))
            {
                return true;
            }
        }
        return false;
    }

    private NameType getLegalNameType()
    {
        try
        {
            return (NameType)getLookupService().getNameTypeByCode(NameType.LEGAL_NAME.getName());
        }
        catch(UnknownLookupCodeException e)
        {
            //ASSERT: Should not happen unless there is a database problem
            throw new RuntimeException(e.getMessage(), e);
        }
        catch(UnknownLookupTypeException e) {
            //ASSERT: Should not happen unless there is a database problem
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.fw.util.builder.AbstractValidator#processValidate(java.lang.Object)
     */
    protected void processValidate(Object input) throws ValidatorException
    {
        this.validateMinimumDataProvided((Person)input);
        this.validateDependencies((Person)input);
        this.validateBirthAndDeathDates((Person)input);
    }

    private void validateMinimumDataProvided(Person input)
        throws ValidatorException
    {
        if((input.getBirthRecord() == null)
            || (input.getBirthRecord().getBirthDate() == null))
        {
            throw new ValidatorException("Date of Birth must be entered");
        }
        else if(!this.containsNameType(input, this.getLegalNameType()))
        {
            throw new ValidatorException("Person must have a legal name");
        }
    }

    private void validateDependencies(Person input) throws ValidatorException
    {
        if(input.getBirthRecord() != null)
        {
            this.birthRecordValidator.validate(input.getBirthRecord());
        }

        if(input.getDeathRecord() != null)
        {
            this.deathRecordValidator.validate(input.getDeathRecord());
        }

        super.validateSet(this.nameValidator, input.getNames());
    }

    private void validateBirthAndDeathDates(Person input)
        throws ValidatorException
    {
        ImpreciseDate birthDate = (input.getBirthRecord() == null)
            ? null
            : input.getBirthRecord().getBirthDate();
        ImpreciseDate deathDate = (input.getDeathRecord() == null)
            ? null
            : input.getDeathRecord().getDeathDate();

        //TODO: Validate that Birth Date is before Death Date
    }
}