/*******************************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ******************************************************************************/
package gov.va.med.esr.common.builder.entity.metaData;

// Java Classes
import java.util.List;

// Framework Classes
import gov.va.med.fw.hl7.segment.MSH;
import gov.va.med.fw.hl7.segment.PID;
import gov.va.med.fw.hl7.segment.ZEL;
import gov.va.med.fw.hl7.segment.ZEM;
import gov.va.med.fw.hl7.segment.ZEN;
import gov.va.med.fw.hl7.segment.ZIO;
import gov.va.med.fw.hl7.segment.ZMH;
import gov.va.med.fw.hl7.segment.ZPD;

// ESR classes
import gov.va.med.esr.common.builder.datatype.metadata.CE;
import gov.va.med.esr.common.builder.datatype.metadata.ID;
import gov.va.med.esr.common.builder.datatype.metadata.ST;
import gov.va.med.esr.common.builder.datatype.metadata.XPN;
import gov.va.med.esr.common.builder.entity.BirthRecordMetaData;
import gov.va.med.esr.common.builder.entity.DeathRecordMetaData;
import gov.va.med.esr.common.builder.entity.NameMetaData;
import gov.va.med.esr.common.builder.entity.PersonMetaData;
import gov.va.med.esr.common.builder.entity.RaceMetaData;
import gov.va.med.esr.common.builder.entity.EthnicityMetaData;
import gov.va.med.esr.common.builder.entity.SSNMetaData;
import gov.va.med.esr.common.model.lookup.NameType;
import gov.va.med.esr.common.model.person.Person;

public class PersonMetaDataFromPID extends AbstractMetaData implements
        PersonMetaData
{
    private Person entity;

    private PID pid;

    private ZPD zpd;

    private ZEM zem;

    private ZEN zen;

    private ZEL zel;
    
    private ZIO zio;

    private BirthRecordMetaData birthRecord;

    private DeathRecordMetaData deathRecord;

    private NameMetaData[] names;

    private CE wasPrisonerOfWarIndicator;

    private SSNMetaData[] ssns;

    private NameMetaData motherName;
    private NameMetaData fatherName;
    
    private RaceMetaData[] races;
    
    private EthnicityMetaData ethnicity;

    private static final int REL_MOTHER = 1;
    private static final int REL_FATHER = 2;
    
    public PersonMetaDataFromPID(PID pid, ZPD zpd, ZEM zem, ZEN zen, ZEL zel,
            MSH msh, List zmhs, ZIO zio)
    {
        super();

        this.pid = pid;
        this.zpd = zpd;
        this.zem = zem;
        this.zen = zen;
        this.zel = zel;
        this.zio = zio;
        
        this.birthRecord = (pid == null) ? null
                : new BirthRecordMetaDataFromPID(pid);
        this.deathRecord = (zpd == null) ? null
                : new DeathRecordMetaDataFromZPD(zpd, msh, false);
        this.names = (pid == null) ? null : this.buildNames(pid);
        this.ssns = (pid == null) ? null : buildSsns();

        processZMHsForPOWIndicator(zmhs);
        
        this.motherName = (pid == null) ? null : buildRelationName(zpd, REL_MOTHER);
        this.fatherName = (pid == null) ? null : buildRelationName(zpd, REL_FATHER);
 
        this.races = (pid == null) ? null : buildRaces();
        this.ethnicity = (pid == null) ? null : new EthnicityMetaDataFromCE(CE
                .create(pid.getEthnicity(), pid.getComponentDelimiter()));
    }

    /**
     * TODO RP 08/16 Add Alias SSNs
     * 
     * @param pid
     * @return
     */
    private SSNMetaData[] buildSsns()
    {

        SSNMetaData[] ssns = new SSNMetaData[1];

        SSNMetaData ssnMetaData = new SSNMetaDataFromPID(pid, zpd);
        ssns[0] = ssnMetaData;

        return ssns;
    }

    private NameMetaData[] buildNames(PID pid)
    {
        return this.buildNames(this.getLegalName(pid), this.getOtherNames(pid));
    }

    private NameMetaData[] buildNames(XPN legalName, XPN[] otherNames)
    {
        int size = (otherNames == null) ? 0 : otherNames.length;
        int sizeWithLegalName = size + ((legalName == null) ? 0 : 1);

        NameMetaData[] results = new NameMetaData[sizeWithLegalName];
        for (int index = 0; index < size; index++)
        {
            results[index] = new NameMetaDataFromXPN(otherNames[index]);
        }
        if (legalName != null)
        {
            results[size] = new NameMetaDataFromXPN(legalName);
        }
        return results;
    }

    private XPN getLegalName(PID pid)
    {
        XPN[] data = XPN.create(pid.getPatientName(), pid.getRepeatDelimiter(),
                pid.getComponentDelimiter());

        if ((data != null) && (data.length > 0))
        {
            XPN legalXPN = data[0];
            if (legalXPN != null)
            {
                legalXPN.setTypeCode(ID.create(NameType.LEGAL_NAME.getName()));
            }
            return legalXPN;
        } else
        {
            return null;
        }
    }

    private XPN[] getOtherNames(PID pid)
    {
        return XPN.create(pid.getPatientAlias(), pid.getRepeatDelimiter(), pid
                .getComponentDelimiter());
    }

    private NameMetaData buildRelationName(ZPD zpd, int relType){

        NameMetaData metaData = null;
    
        String dataString = null;
        switch(relType) {
           case REL_MOTHER:
            dataString = zpd.getMotherName();
            break;
           case REL_FATHER:
            dataString = zpd.getFatherName();
            break;
        }
        
        if (dataString != null) {
            ST data = ST.createForParent(dataString);
            metaData = new NameMetaDataFromST(data);
        }
        
        return metaData;
    }

    
    private RaceMetaData[] buildRaces()
    {
        RaceMetaData[] results = null;
        
        CE[] data = CE.create(pid.getRace(), pid.getRepeatDelimiter(),
                pid.getComponentDelimiter());

        if ((data != null) && (data.length > 0))
        {
           int size = data.length;
            
           results = new RaceMetaData[size];
           for (int index = 0; index < size; index++)
            {
                results[index] = new RaceMetaDataFromCE(data[index]);
            }
         }
         return results;
     }
    
    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.builder.entity.PersonMetaData#getEntity()
     */
    public Person getEntity()
    {
        return this.entity;
    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.builder.entity.PersonMetaData#setEntity(gov.va.med.esr.common.model.person.Person)
     */
    public void setEntity(Person entity)
    {
        this.entity = entity;
    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.builder.entity.PersonMetaData#getBirthRecord()
     */
    public BirthRecordMetaData getBirthRecord()
    {
        return this.birthRecord;
    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.builder.entity.PersonMetaData#getDeathRecord()
     */
    public DeathRecordMetaData getDeathRecord()
    {
        return this.deathRecord;
    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.builder.entity.PersonMetaData#getGender()
     */
    public String getGender()
    {
        return (this.pid == null) ? null : this.pid.getSex();
    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.builder.entity.PersonMetaData#getMaritalStatus()
     */
    public String getMaritalStatus()
    {
        return (this.pid == null) ? null : this.pid.getMaritalStatus();
    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.builder.entity.PersonMetaData#getNames()
     */
    public NameMetaData[] getNames()
    {
        return this.names;
    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.builder.entity.PersonMetaData#getNationalICN()
     */
    public String getNationalICN()
    {
        return (this.pid == null) ? null : this.pid.getPrimaryID();
    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.builder.entity.PersonMetaData#getPreferredFacility()
     */
    public String getPreferredFacility()
    {
        return (this.zen == null) ? null : this.zen.getPreferredFacility();
    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.builder.entity.PersonMetaData#getRace()
     */
    public String getRace()
    {
        return (this.zpd == null) ? null : this.zpd.getRace();
    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.builder.entity.PersonMetaData#getSSN()
     */
    public SSNMetaData[] getSsns()
    {
        return ssns;
    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.builder.entity.PersonMetaData#getVeteran()
     */
    public String getVeteran()
    {
        return (this.zel == null) ? null : this.zel.getVeteran();
    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.builder.entity.MilitaryServiceMetaData#getWasPrisonerOfWar()
     */
    public String getWasPrisonerOfWar()
    {
        return (this.wasPrisonerOfWarIndicator == null) ? null : super
                .getValue(this.wasPrisonerOfWarIndicator.getID());
    }

    private boolean isPOW(String type)
    {
        return ("POW".equals(type));
    }
    
    public String getAppointmentRequestOn1010EZ()
    {
        return (this.zio == null) ? null : this.zio.getAppointmentRequestOn1010EZ();
    }
    public String getAppointmentRequestDate()
    {
        return (this.zio == null) ? null : this.zio.getAppointmentRequestDate();
    }    
    
    public String getEmergencyResponseType()
    {
        return (this.zpd == null) ? null : this.zpd.getEmergencyResponseType();
    }
    
    public NameMetaData getMotherName()
    {
        return this.motherName;
    }

    public NameMetaData getFatherName()
    {
        return this.fatherName;
    }

    public EthnicityMetaData getEthnicity() {
        return ethnicity;
    }

    public void setEthnicity(EthnicityMetaData ethnicity) {
        this.ethnicity = ethnicity;
    }

    public RaceMetaData[] getRaces() {
        return races;
    }

    public void setRaces(RaceMetaData[] races) {
        this.races = races;
    }

    /**
     * Loops thorugh the list of ZMHs, determines if the veteran is a POW,
     * creates a CE for getting the POW indicator
     * 
     * @param zmhs
     *            List of ZMHs
     */
    private void processZMHsForPOWIndicator(List zmhs)
    {
        for (int index = 0; index < ((zmhs == null) ? 0 : zmhs.size()); index++)
        {
            ZMH zmh = (ZMH) zmhs.get(index);
            String type = zmh.getMilitaryHistoryType();
            if (isPOW(type))
            {
                this.wasPrisonerOfWarIndicator = CE.create(zmh
                        .getServiceIndicator(), zmh.getComponentDelimiter());
            }
        }
    }

    public String getReligion() 
    {    
        return (this.pid == null) ? null : this.pid.getReligion();
    }
 
    public String getMothersMaidenName()
    {
        return (this.pid == null) ? null : this.pid.getMotherMaidenName();
    }
    
//    public String getPreferredLanguangeIndicator() {
//        return (this.zpd == null) ? null : this.zpd.getPreferredLanguageIndicator();
//    }
//    
//    public String getPreferredLanguangeDateTime() {
//        return (this.zpd == null) ? null : this.zpd.getPreferredLanguageDateTime();
//    }
}