/**
 *
 */
package gov.va.med.esr.voa.webservice.builder.impl;


import java.util.Date;
import java.util.Iterator;
import java.util.List;

import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.model.ee.Application;
import gov.va.med.esr.common.model.insurance.InsurancePolicy;
import gov.va.med.esr.common.model.insurance.InsuranceSubscriber;
import gov.va.med.esr.common.model.insurance.Medicare;
import gov.va.med.esr.common.model.insurance.PrivateInsurance;
import gov.va.med.esr.common.model.lookup.AddressChangeSource;
import gov.va.med.esr.common.model.lookup.InsuredRelationship;
import gov.va.med.esr.common.model.lookup.NameType;
import gov.va.med.esr.common.model.lookup.PhoneSourceOfChange;
import gov.va.med.esr.common.model.lookup.SSNType;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.party.Address;
import gov.va.med.esr.common.model.party.Email;
import gov.va.med.esr.common.model.party.Phone;
import gov.va.med.esr.common.model.person.BirthRecord;
import gov.va.med.esr.common.model.person.Employment;
import gov.va.med.esr.common.model.person.Ethnicity;
import gov.va.med.esr.common.model.person.Name;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.PreferredFacility;
import gov.va.med.esr.common.model.person.Race;
import gov.va.med.esr.common.model.person.SSN;
import gov.va.med.esr.service.PersonIdentityTraits;
import gov.va.med.esr.voa.webservice.AddressInfo;
import gov.va.med.esr.voa.webservice.ApplicationInfo;
import gov.va.med.esr.voa.webservice.EmailInfo;
import gov.va.med.esr.voa.webservice.EmploymentInfo;
import gov.va.med.esr.voa.webservice.InsuranceInfo;
import gov.va.med.esr.voa.webservice.PersonInfo;
import gov.va.med.esr.voa.webservice.PhoneInfo;
import gov.va.med.esr.voa.webservice.SubmitFormRequest;
import gov.va.med.esr.voa.webservice.VeteranIdentifier;
import gov.va.med.esr.voa.webservice.builder.DemographicsBuilderFactory;
import gov.va.med.ps.model.PersonVPID;

/**
 * @author DNS   CHINNR
 *
 */
public class DemographicsBuilderFactoryImpl implements DemographicsBuilderFactory {

	private TypesHelper typesHelper = new TypesHelper();
	private BuildHelper buildHelper = new BuildHelper();

	@SuppressWarnings("rawtypes")
	public void buildDemographics(Person person,SubmitFormRequest submitFormRequest) throws Exception {

		PersonInfo personInfo = submitFormRequest.getForm().getSummary().getPersonInfo();

		 VeteranIdentifier vid = submitFormRequest.getIdentity().getVeteranIdentifier();
		 PersonIdentityTraits pidt = new PersonIdentityTraits();
		 Name name = new Name();

		 if(personInfo != null){

			 if(personInfo.getLastName() != null)name.setFamilyName(personInfo.getLastName());
			 if(personInfo.getFirstName() != null)name.setGivenName(personInfo.getFirstName());
			 // As per the discussion, the nametype is set as legal name. VOA won't send the name type
			 name.setType(this.typesHelper.getNameType(NameType.LEGAL_NAME.getCode()));
			 if(personInfo.getMiddleName() != null)name.setMiddleName(personInfo.getMiddleName());

			 if(personInfo.getSuffix() != null)name.setSuffix(personInfo.getSuffix());
			 person.addName(name);
			 pidt.addName(name);
			 if(personInfo.getMothersMaidenName() != null){
				 person.setMothersMaidenName(personInfo.getMothersMaidenName());
				 pidt.setMothersMaidenName(personInfo.getMothersMaidenName());
				}
			 if (vid != null) {
				 PersonVPID vpid = new PersonVPID(vid.getValue());
				 person.setVPID(vpid);
			 }
			 SSN ssn = new SSN();
			 if(personInfo.getSsnText() != null){
				 ssn.setSsnText(personInfo.getSsnText());
				 //ssntype is active default
				 ssn.setType(typesHelper.getSSNType(SSNType.CODE_ACTIVE.getCode()));
			 }

			 pidt.setSsn(ssn);
			 person.addSsn(ssn);
			 //Gender
			 if(personInfo.getGender() != null){
				 person.setGender(typesHelper.getGender(personInfo.getGender()));
				 pidt.setGender(typesHelper.getGender(personInfo.getGender()));
			 }

		 }

		 // Birth record

		 BirthRecord birthRecord = person.getBirthRecord();
		 if(birthRecord == null ) birthRecord = new BirthRecord();
		 if(personInfo.getPlaceOfBirthCity() != null){
			 birthRecord.setCity(personInfo.getPlaceOfBirthCity());
			 pidt.setPlaceOfBirthCity(personInfo.getPlaceOfBirthCity());
		 }
		 if(personInfo.getPlaceOfBirthState() != null){
			 birthRecord.setState(personInfo.getPlaceOfBirthState());
			 pidt.setPlaceOfBirthState(personInfo.getPlaceOfBirthState());
		 }
		 if(personInfo.getDob() != null){
			 ImpreciseDate id = new ImpreciseDate(buildHelper.stringToDate(personInfo.getDob()));
			 birthRecord.setBirthDate(id);
		 }
		 person.setBirthRecord(birthRecord);
		 pidt.setBirthRecord(birthRecord);

		//Marital status

		if(submitFormRequest.getForm().getSummary().getDemographics() != null && submitFormRequest.getForm().getSummary().getDemographics().getMaritalStatus() != null){
			person.setMaritalStatus(this.typesHelper.getMaritalStatus(submitFormRequest.getForm().getSummary().getDemographics().getMaritalStatus()));
		}

		if(submitFormRequest.getForm().getSummary().getDemographics() != null && submitFormRequest.getForm().getSummary().getDemographics().isAppointmentRequestResponse() != null) {
		 person.setAppointmentRequestResponse(submitFormRequest.getForm().getSummary().getDemographics().isAppointmentRequestResponse());
		 person.setAppointmentRequestDate(new Date());
		}

		//ethinicity
		if(submitFormRequest.getForm().getSummary().getDemographics() != null && submitFormRequest.getForm().getSummary().getDemographics().getEthnicity() != null){
			Ethnicity et = new Ethnicity();
			et.setEthnicityType(this.typesHelper.getEthnicityType(submitFormRequest.getForm().getSummary().getDemographics().getEthnicity()));
			person.setEthnicity(et);

		}

		 // Relogion

		 if(submitFormRequest.getForm().getSummary().getDemographics() != null &&
				 submitFormRequest.getForm().getSummary().getDemographics().getReligion() != null && !submitFormRequest.getForm().getSummary().getDemographics().getReligion().isEmpty()){
		 	person.setReligion(this.typesHelper.getReligion(submitFormRequest.getForm().getSummary().getDemographics().getReligion()));
		}
		 //Races
		if( submitFormRequest.getForm().getSummary().getDemographics() != null && submitFormRequest.getForm().getSummary().getDemographics().getRaces() != null){
		   List<String> races = submitFormRequest.getForm().getSummary().getDemographics().getRaces().getRace();

		if (races != null) {
			Iterator raceIter = races.iterator();
			while (raceIter.hasNext()) {
				String racestring = (String) raceIter.next();
				if (racestring != null && !racestring.isEmpty()) {
					Race race = new Race();
					race.setRaceType(this.typesHelper.getRaceType(racestring));
					person.addRace(race);
				}
			}
		}
		}
		//  preferred facility
		if(submitFormRequest.getForm().getSummary().getDemographics() != null && submitFormRequest.getForm().getSummary().getDemographics().getPreferredFacility() != null){

				PreferredFacility pf = new PreferredFacility();
				pf.setFacility(this.typesHelper.getVAFacility(submitFormRequest.getForm().getSummary().getDemographics().getPreferredFacility()));
				person.addPreferredFacility(pf);

		}

		//CCR12789: Affordable Care Act acaIndicator
		if(submitFormRequest.getForm().getSummary().getDemographics() != null && submitFormRequest.getForm().getSummary().getDemographics().isAcaIndicator() != null){
			//not in use in ES yet, ACA indicator not exist
			//person.setAcaIndicator(submitFormRequest.getForm().getSummary().getDemographics().isAcaIndicator());
		}


		//permanent address
		Address address = person.getPermanentAddress();
		if(address == null) {
			address = new Address();
		}
		if(submitFormRequest.getForm().getSummary().getDemographics()!= null &&
				submitFormRequest.getForm().getSummary().getDemographics().getContactInfo() != null &&
				submitFormRequest.getForm().getSummary().getDemographics().getContactInfo().getAddresses()!= null) {

			List<AddressInfo> addressList = submitFormRequest.getForm().getSummary().getDemographics().getContactInfo().getAddresses().getAddress();

			Iterator addressIter = addressList.iterator();

			while (addressIter.hasNext()) {
				AddressInfo addressInfo = (AddressInfo)addressIter.next();
				address = buildHelper.buildAddressInfo(addressInfo);

			   try {
				   address.setChangeDate(new Date());
				   address.setChangeSource(this.typesHelper.getLookupService().getAddressChangeSourceByCode(
			            AddressChangeSource.CODE_HEC.getName()));
				   address.setChangeSite(this.typesHelper.getLookupService().getVaFacilityByCode(VAFacility.CODE_HEC.getName()));
			   } catch (Exception ex) {
				   throw new Exception(ex);
			   }
				person.addAddress(address);
				pidt.addAddress(address);

			}

		}
		//Phone
		if(submitFormRequest.getForm().getSummary().getDemographics() != null &&
				submitFormRequest.getForm().getSummary().getDemographics().getContactInfo() != null &&
				submitFormRequest.getForm().getSummary().getDemographics().getContactInfo().getPhones() != null){

			List<PhoneInfo> phoneList = submitFormRequest.getForm().getSummary().getDemographics().getContactInfo().getPhones().getPhone();
			Iterator phoneIter = phoneList.iterator();
			while (phoneIter.hasNext()) {
				PhoneInfo phInfo = (PhoneInfo) phoneIter.next();
				Phone phone = new Phone();
				if(phInfo != null ) {
					if(phInfo.getType() != null) {
						phone.setType(typesHelper.getPhoneType(phInfo.getType()));
					} else {
						phone.setType(typesHelper.getPhoneType("1"));
					}
					if(phInfo.getPhoneNumber() != null && phInfo.getPhoneNumber().length() == 10) {
						String num = String.format("(%s) %s-%s", phInfo.getPhoneNumber().substring(0, 3), phInfo.getPhoneNumber().substring(3, 6),
								phInfo.getPhoneNumber().substring(6, 10));
						phone.setPhoneNumber(num);
					}
					try {
						phone.setChangeDate(new Date());
						phone.setSourceOfChange(this.typesHelper.getLookupService().getPhoneSourceOfChangeByCode(PhoneSourceOfChange.CODE_HEC.getName()));//CCR12588
						phone.setSiteOfChange(this.typesHelper.getLookupService().getVaFacilityByCode(VAFacility.CODE_HEC.getName()));
					} catch (Exception ex) {
						throw new Exception (ex);
					}
					person.addPhone(phone);
				}

			}
		}
		//Email address
		if(submitFormRequest.getForm().getSummary().getDemographics() != null &&
				submitFormRequest.getForm().getSummary().getDemographics().getContactInfo()!= null &&
				submitFormRequest.getForm().getSummary().getDemographics().getContactInfo().getEmails() != null){
			List<EmailInfo> emailList = submitFormRequest.getForm().getSummary().getDemographics().getContactInfo().getEmails().getEmail();
			if(emailList != null){
				Iterator emailIter = emailList.iterator();
				while (emailIter.hasNext()) {
					EmailInfo emInfo = (EmailInfo) emailIter.next();
					Email email = new Email();
					if(emInfo != null) {
						if(emInfo.getType() != null ) {
							email.setType(typesHelper.getEmailType(emInfo.getType()));
						} else {
							//set email type as Personal
							email.setType(typesHelper.getEmailType("1"));
						}
						if(emInfo.getAddress() != null)email.setAddress(emInfo.getAddress());

						try {
							email.setChangeDate(new Date());
							email.setSourceOfChange(this.typesHelper.getLookupService().getEmailSourceOfChangeByCode(PhoneSourceOfChange.CODE_HEC.getName()));
							email.setSiteOfChange(this.typesHelper.getLookupService().getVaFacilityByCode(VAFacility.CODE_HEC.getName()));
						} catch (Exception ex) {
							throw new Exception (ex);
						}

						person.addEmail(email);
					}

				}
			}
		}
		//Association
		//do not accept any association from 1010


		// Employment Info
		if(submitFormRequest.getForm().getSummary().getEmploymentInfo() != null){
			Employment employment = new Employment();
			 EmploymentInfo employmentInfo = (EmploymentInfo)submitFormRequest.getForm().getSummary().getEmploymentInfo();
			 if(employmentInfo != null) {
				 employment= buildHelper.buildEmployment(employmentInfo);
				 person.setEmployment(employment);
			 }
		}

		 //Application
		 buildApplication(person,submitFormRequest);
		 //insurance
		 buildInsurance(person,submitFormRequest);

	}


	@SuppressWarnings("rawtypes")
	private void buildApplication(Person person,SubmitFormRequest submitFormRequest){

		if(submitFormRequest.getForm().getApplications().getApplicationInfo() != null &&
					submitFormRequest.getForm().getApplications().getApplicationInfo() != null){
			List<ApplicationInfo> appList = submitFormRequest.getForm().getApplications().getApplicationInfo();
			 Iterator itr =  appList.iterator();
				while (itr != null && itr.hasNext()) {
					ApplicationInfo applicationInfo = (ApplicationInfo)itr.next();
					Application application = new Application();

					if(applicationInfo != null ){
						if(applicationInfo.getAppMethod() != null) {
						  application.setAppliactionMethod(this.typesHelper.getApplicationMethod("1"));
						}
						if(applicationInfo.getAppDate() != null)application.setApplicationDate(buildHelper.getDateXMLtoJava(applicationInfo.getAppDate()));
						if(applicationInfo.getBenefitType() != null)
						application.setBenefitType(this.typesHelper.getBenefitType(applicationInfo.getBenefitType()));
					}
					person.setApplication(application);

			}
		}
 }


	@SuppressWarnings("rawtypes")
	private  void buildInsurance(Person person,SubmitFormRequest submitFormRequest) throws Exception {
		//
		if(submitFormRequest.getForm().getSummary().getInsuranceList() != null &&
				submitFormRequest.getForm().getSummary().getInsuranceList().getInsurance() != null) {
		List<InsuranceInfo> insuranceList = submitFormRequest.getForm().getSummary().getInsuranceList().getInsurance();
		Iterator itr =  insuranceList.iterator();
		while (itr != null && itr.hasNext()) {
			InsuranceInfo insuranceInfo = (InsuranceInfo)itr.next();
			InsurancePolicy insurance = null;

			if(insuranceInfo.getInsuranceMappingTypeName() != null ){
				//CCR 13311 remove medicare partB
				if( insuranceInfo.getInsuranceMappingTypeName().equalsIgnoreCase("MDCR") &&
						//CCR13302 make sure either PartA or PartB is true before creating Medicare object
						((insuranceInfo.isEnrolledInPartA() != null && insuranceInfo.isEnrolledInPartA()))) {/* ||
						 (insuranceInfo.isEnrolledInPartB() != null && insuranceInfo.isEnrolledInPartB())) ){ */
					insurance = new Medicare();

				}

				if(	insuranceInfo.getInsuranceMappingTypeName().equalsIgnoreCase("PI")){
					insurance = new PrivateInsurance();

				}
			}

		if(insurance != null){
			if(insuranceInfo.getCompanyName() != null)insurance.setCompanyName(insuranceInfo.getCompanyName());
			if(insuranceInfo.getGroupNumber() != null)insurance.setGroupNumber(insuranceInfo.getGroupNumber());
			if(insuranceInfo.getGroupName() != null)insurance.setGroupName(insuranceInfo.getGroupName());
			InsuranceSubscriber insubr = insurance.getSubscriber();
			if(insubr == null ) insubr = new InsuranceSubscriber();
			if(insuranceInfo.getPolicyHolderName() != null) insubr.setName(insuranceInfo.getPolicyHolderName());

			if (insurance instanceof PrivateInsurance) {
				//try to match relationship with name of vet or spouse
				try {
					String vetFirstName = submitFormRequest.getForm().getSummary().getPersonInfo().getFirstName();
					String vetLastName = submitFormRequest.getForm().getSummary().getPersonInfo().getLastName();
					boolean matched = false;

					if (insubr.getName() != null) {

						if (insubr.getName().toLowerCase().indexOf(vetFirstName.toLowerCase()) >= 0 && insubr.getName().toLowerCase().indexOf(vetLastName.toLowerCase()) >= 0) {
							insubr.setRelationship(this.typesHelper.getLookupService().getInsuredRelationshipByCode(InsuredRelationship.CODE_VETERAN.getCode()));
							matched = true;
						}
						else {
							if (submitFormRequest.getForm().getSummary().getFinancialsInfo() != null &&
									submitFormRequest.getForm().getSummary().getFinancialsInfo().getFinancialStatement() != null &&
									submitFormRequest.getForm().getSummary().getFinancialsInfo().getFinancialStatement().getSpouseFinancialsList() != null &&
									submitFormRequest.getForm().getSummary().getFinancialsInfo().getFinancialStatement().getSpouseFinancialsList().getSpouseFinancials() != null &&
									submitFormRequest.getForm().getSummary().getFinancialsInfo().getFinancialStatement().getSpouseFinancialsList().getSpouseFinancials().get(0) != null &&
									submitFormRequest.getForm().getSummary().getFinancialsInfo().getFinancialStatement().getSpouseFinancialsList().getSpouseFinancials().get(0).getSpouse() != null) {

								String spouseFirstName = submitFormRequest.getForm().getSummary().getFinancialsInfo().
										getFinancialStatement().getSpouseFinancialsList().getSpouseFinancials().get(0).getSpouse().getGivenName();
								String spouseLastName = submitFormRequest.getForm().getSummary().getFinancialsInfo().
										getFinancialStatement().getSpouseFinancialsList().getSpouseFinancials().get(0).getSpouse().getFamilyName();

								if (insubr.getName().toLowerCase().indexOf(spouseFirstName.toLowerCase()) >= 0 && insubr.getName().toLowerCase().indexOf(spouseLastName.toLowerCase()) >= 0) {
									insubr.setRelationship(this.typesHelper.getLookupService().getInsuredRelationshipByCode(InsuredRelationship.CODE_SPOUSE.getCode()));
									matched = true;
								}
							}

						}
					}
					if (!matched) {
						insubr.setRelationship(this.typesHelper.getLookupService().getInsuredRelationshipByCode(InsuredRelationship.CODE_OTHER.getCode()));
					}
				} catch (Exception ex) {
					System.out.println("error in insurance:" + ex.getMessage());
					insubr.setRelationship(this.typesHelper.getLookupService().getInsuredRelationshipByCode(InsuredRelationship.CODE_OTHER.getCode()));
				}

			} else {

				try {
					insubr.setRelationship(this.typesHelper.getLookupService().getInsuredRelationshipByCode(InsuredRelationship.CODE_VETERAN.getCode()));
				} catch (Exception ex) {
					throw new Exception (ex);
				}
			}
			insurance.setSubscriber(insubr);

			AddressInfo addressInfo = insuranceInfo.getInsAddress();
			if(addressInfo != null)
			insurance.setAddress(buildHelper.buildAddressInfo(addressInfo));
			//  There is  no phone number list for voa. phone is part of address.
			if(insuranceInfo.getInsurancePhones() != null && insuranceInfo.getInsurancePhones().getPhone() != null){
				List<PhoneInfo> phoneList = insuranceInfo.getInsurancePhones().getPhone();
				Iterator phoneItr = phoneList.iterator();

				while ( phoneItr.hasNext())
				{

					PhoneInfo pInfo = (PhoneInfo)phoneItr.next();
					Phone phone = new Phone();
					if(pInfo.getPhoneNumber() != null)phone.setPhoneNumber(pInfo.getPhoneNumber());


					if ( pInfo.getType() != null)
					{

						if(pInfo.getType().equalsIgnoreCase("2") || pInfo.getType().equalsIgnoreCase("6")){
						phone.setType(typesHelper.getPhoneType("2"));
						insurance.setBusinessPhone(phone);
						}

						if(pInfo.getType().equalsIgnoreCase("3")){
							phone.setType(typesHelper.getPhoneType(pInfo.getType()));
							insurance.setFax(phone);
							}
						if(pInfo.getType().equalsIgnoreCase("7")){
							phone.setType(typesHelper.getPhoneType(pInfo.getType()));
							insurance.setPreCertificationPhone(phone);
							}
					}

				}
			}

			if (insurance instanceof PrivateInsurance) {

				if ( insuranceInfo.getPolicyEffectiveDate() != null)
					((PrivateInsurance) insurance).setPolicyEffectiveDate(new ImpreciseDate(insuranceInfo.getPolicyEffectiveDate()));

				if ( insuranceInfo.getPolicyExpirationDate() != null)
					((PrivateInsurance) insurance).setPolicyExpirationDate(new ImpreciseDate(insuranceInfo.getPolicyExpirationDate()));
				if(insuranceInfo.getPolicyNumber() != null)((PrivateInsurance) insurance).setPolicyNumber(insuranceInfo.getPolicyNumber());

				person.addInsurance(insurance);


			} else if (insurance instanceof Medicare) {

					if(insuranceInfo.isEnrolledInPartA() != null){

					//12094 - still set the indicator if it is false, and only set details if the indicator is true
					((Medicare) insurance).setEnrolledInPartA(insuranceInfo.isEnrolledInPartA());
					if (insuranceInfo.isEnrolledInPartA())
					{
						if(insuranceInfo.getPartAEffectiveDate() != null)
							((Medicare) insurance).setPartAEffectiveDate(new ImpreciseDate(insuranceInfo.getPartAEffectiveDate()));
						if(insuranceInfo.getSubscriber() != null) ((Medicare) insurance).setNameOnMedicareCard(insuranceInfo.getSubscriber());
						if(insuranceInfo.getPolicyNumber() != null)((Medicare) insurance).setMedicareClaimNumber(insuranceInfo.getPolicyNumber());
					}

					try {
						insurance.setReportSite(this.typesHelper.getLookupService().getVaFacilityByStationNumber(VAFacility.CODE_MHV.getCode()));
					} catch (Exception e) {
						throw new Exception (e);
					}

					person.addInsurance(insurance);

				}

			}

		}
		}
	}
  }

}
