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

// Java Classes
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

// Library Classes

// Framework Classes
import gov.va.med.fw.util.builder.Builder;
import gov.va.med.fw.util.builder.BuilderException;

// Common Classes
import gov.va.med.esr.common.model.ee.CDCondition;
import gov.va.med.esr.common.model.ee.CDDescriptor;
import gov.va.med.esr.common.model.ee.CDDiagnosis;
import gov.va.med.esr.common.model.ee.CDProcedure;
import gov.va.med.esr.common.model.ee.CatastrophicDisability;
import gov.va.med.esr.common.model.ee.ClinicalDetermination;
import gov.va.med.esr.common.model.ee.MilitarySexualTrauma;
import gov.va.med.esr.common.model.ee.NoseThroatRadium;
import gov.va.med.esr.common.model.ee.SpinalCordInjury;
import gov.va.med.esr.common.model.lookup.CDDeterminationMethod;
import gov.va.med.esr.common.model.lookup.MilitarySexualTraumaStatus;
import gov.va.med.esr.common.model.lookup.NTRVerificationMethod;
import gov.va.med.esr.common.model.lookup.SpinalCordInjuryType;

// Messaging Classess

/**
 * Class that builds the application from a message.
 *
 * @author Carlos Ruiz
 * @version 1.0
 */
public class ClinicalDeterminationBuilder extends EntityBuilder {
	/**
	 * An instance of serialVersionUID
	 */
	private static final long serialVersionUID = 6174603347610993423L;

	/**
	 * Default constructor.
	 */
	public ClinicalDeterminationBuilder() {
		super();
	}

	private boolean shouldKeep(ClinicalDetermination obj) {
		return true;
	}

	private void transfer(ClinicalDetermination input,
			ClinicalDeterminationMetaData metaData) throws BuilderException {
		input.setDeterminationFacility(super.build(input
				.getDeterminationFacility(), metaData.getDeterminationFacility()));
	}

	public static class CatastrophicDisabilityBuilder extends
			ClinicalDeterminationBuilder {
		/**
		 * An instance of serialVersionUID
		 */
		private static final long serialVersionUID = -4077674606845434700L;

		private Builder conditionBuilder;

		private Builder determinationMethodBuilder;

		private Builder diagnosisBuilder;

		private Builder procedureBuilder;

        private Builder descriptorBuilder;
        
		public CatastrophicDisabilityBuilder() {
			super();
		}

		public Builder getConditionBuilder() {
			return this.conditionBuilder;
		}

		public void setConditionBuilder(Builder conditionBuilder) {
			this.conditionBuilder = conditionBuilder;
		}

		public Builder getDeterminationMethodBuilder() {
			return this.determinationMethodBuilder;
		}

		public void setDeterminationMethodBuilder(
				Builder determinationMethodBuilder) {
			this.determinationMethodBuilder = determinationMethodBuilder;
		}

		public Builder getDiagnosisBuilder() {
			return this.diagnosisBuilder;
		}

		public void setDiagnosisBuilder(Builder diagnosisBuilder) {
			this.diagnosisBuilder = diagnosisBuilder;
		}

		public Builder getProcedureBuilder() {
			return this.procedureBuilder;
		}

		public void setProcedureBuilder(Builder procedureBuilder) {
			this.procedureBuilder = procedureBuilder;
		}
        
        public Builder getDescriptorBuilder() {
                return descriptorBuilder;
        }

         public void setDescriptorBuilder(Builder descriptorBuilder) {
                this.descriptorBuilder = descriptorBuilder;
        }

		public CatastrophicDisability build(
				CatastrophicDisabilityMetaData metaData) throws BuilderException {
			CatastrophicDisability input = metaData.getEntity();
			CatastrophicDisability output = (input == null) ? new CatastrophicDisability()
					: input;

			this.transfer(output, metaData);

			return this.shouldKeep(output) ? output : null;
		}

		private CDCondition buildCondition(CDCondition input,
				CDConditionMetaData metaData) throws BuilderException {
			if (metaData == null) {
				return null;
			}
			else {
				metaData.setEntity(input);
				return (CDCondition) this.conditionBuilder.build(metaData);
			}
		}

		private void buildConditions( CatastrophicDisability input,
				CDConditionMetaData[] metaData) throws BuilderException {
			Set toAdd = new HashSet();

			for (int index = 0; index < ((metaData == null) ? 0 : metaData.length); index++) {
				this.processCondition(toAdd, metaData[index]);
			}

			input.removeAllConditions();

			for (Iterator i = toAdd.iterator(); i.hasNext();) {
				input.addCondition((CDCondition) i.next());
			}
		}

		private CDDeterminationMethod buildDeterminationMethod(
				CDDeterminationMethod input, String code) throws BuilderException {
			return super.shouldDelete(code) ? null : (CDDeterminationMethod) super
					.build(this.determinationMethodBuilder, input, code);
		}

		private CDDiagnosis buildDiagnosis(CDDiagnosis input,
				CDDiagnosisMetaData metaData) throws BuilderException {
			if (metaData == null) {
				return null;
			}
			else {
				metaData.setEntity(input);
				return (CDDiagnosis) this.diagnosisBuilder.build(metaData);
			}
		}

		private void buildDiagnoses(CatastrophicDisability input,
				CDDiagnosisMetaData[] metaData) throws BuilderException {
			Set toAdd = new HashSet();

			for (int index = 0; index < ((metaData == null) ? 0 : metaData.length); index++) {
				this.processDiagnosis(toAdd, metaData[index]);
			}

			input.removeAllDiagnoses();

			for (Iterator i = toAdd.iterator(); i.hasNext();) {
				input.addDiagnosis((CDDiagnosis) i.next());
			}
		}

		private CDProcedure buildProcedure(CDProcedure input,
				CDProcedureMetaData metaData) throws BuilderException {
			if (metaData == null) {
				return null;
			}
			else {
				metaData.setEntity(input);
				return (CDProcedure) this.procedureBuilder.build(metaData);
			}
		}

		private void buildProcedures(CatastrophicDisability input,
				CDProcedureMetaData[] metaData) throws BuilderException {
			Set toAdd = new HashSet();
			Set toRemove = new HashSet(input.getProcedures());

			for (int index = 0; index < ((metaData == null) ? 0 : metaData.length); index++) {
				this.processProcedure(toAdd, metaData[index]);
			}

			for (Iterator i = toRemove.iterator(); i.hasNext();) {
				input.removeProcedure((CDProcedure) i.next());
			}

			for (Iterator i = toAdd.iterator(); i.hasNext();) {
				input.addProcedure((CDProcedure) i.next());
			}
		}
        
        private CDDescriptor buildDescriptor(CDDescriptor input,
                CDDescriptorMetaData metaData) throws BuilderException {
            if (metaData == null) {
                return null;
            }
            else {
                metaData.setEntity(input);
                return (CDDescriptor) this.descriptorBuilder.build(metaData);
            }
        }

        private void buildDescriptors( CatastrophicDisability input,
                CDDescriptorMetaData[] metaData) throws BuilderException {
            Set toAdd = new HashSet();

            for (int index = 0; index < ((metaData == null) ? 0 : metaData.length); index++) {
                this.processDescriptor(toAdd, metaData[index]);
            }

            input.removeAllCDDescriptors();

            for (Iterator i = toAdd.iterator(); i.hasNext();) {
                input.addCDDescriptor((CDDescriptor) i.next());
            }
        }


		private boolean shouldKeep(CatastrophicDisability obj) {
			return (super.shouldKeep((ClinicalDetermination) obj));
		}

		private void processCondition(Set toAdd, CDConditionMetaData metaData)
				throws BuilderException {
			CDCondition value = this.buildCondition(null, metaData);
			if (value != null) {
				toAdd.add(value);
			}
		}

		private void processDiagnosis(Set toAdd, CDDiagnosisMetaData metaData)
				throws BuilderException {
			CDDiagnosis value = this.buildDiagnosis(null, metaData);
			if (value != null) {
				toAdd.add(value);
			}
		}

		private void processProcedure(Set toAdd, CDProcedureMetaData metaData)
				throws BuilderException {
			CDProcedure value = this.buildProcedure(null, metaData);
			if (value != null) {
				toAdd.add(value);
			}
		}
        
        private void processDescriptor(Set toAdd, CDDescriptorMetaData metaData)
        throws BuilderException {
            CDDescriptor value = this.buildDescriptor(null, metaData);
            if (value != null) {
                toAdd.add(value);
            }
        }

		private void transfer(CatastrophicDisability input,
				CatastrophicDisabilityMetaData metaData) throws BuilderException {
			super.transfer((ClinicalDetermination) input, metaData);
			input.setDecisionDate(super.build(input
					.getDecisionDate(), metaData
					.getDeterminationDate()));
			input.setDeterminationMethod(this.buildDeterminationMethod(input
					.getDeterminationMethod(), metaData.getDeterminationMethod()));
			input.setDeterminedBy(super.build(input.getDeterminedBy(), metaData
					.getDeterminedBy()));
			input.setCatastrophicallyDisabled(super.build(input
					.isCatastrophicallyDisabled(), metaData
					.getCatastrophicallyDisabled()));
			input.setReviewDate(super.build(input.getReviewDate(), metaData
					.getReviewDate()));
			input.setVeteranRequestedCDReviewDate(super.build(input
					.getVeteranRequestedCDReviewDate(), metaData
					.getVeteranRequestedCDReviewDate()));
			input.setFacilityInitiatedCDReviewDate(super.build(input
					.getFacilityInitiatedCDReviewDate(), metaData
					.getFacilityInitiatedCDReviewDate()));
			input.setVeteranWasNotifiedCDDate(super.build(input
					.getVeteranWasNotifiedCDDate(), metaData
					.getVeteranWasNotifiedCDDate()));

			this.buildConditions(input, metaData.getConditions());
			this.buildDiagnoses(input, metaData.getDiagnoses());
			this.buildProcedures(input, metaData.getProcedures());
            this.buildDescriptors(input, metaData.getDescriptors());
		}

      
	}

	public static class MilitarySexualTraumaBuilder extends
			ClinicalDeterminationBuilder {
		/**
		 * An instance of serialVersionUID
		 */
		private static final long serialVersionUID = -7040141910177316654L;

		private Builder statusBuilder;

		public MilitarySexualTraumaBuilder() {
			super();
		}

		public Builder getStatusBuilder() {
			return this.statusBuilder;
		}

		public void setStatusBuilder(Builder statusBuilder) {
			this.statusBuilder = statusBuilder;
		}

		public MilitarySexualTrauma build(MilitarySexualTraumaMetaData metaData)
				throws BuilderException {
			MilitarySexualTrauma input = metaData.getEntity();
			MilitarySexualTrauma output = (input == null) ? new MilitarySexualTrauma()
					: input;

			this.transfer(output, metaData);

			return this.shouldKeep(output) ? output : null;
		}

		private MilitarySexualTraumaStatus buildStatus(
				MilitarySexualTraumaStatus input, String code)
				throws BuilderException {
			return (MilitarySexualTraumaStatus) super.build(this.statusBuilder,
					input, code);
		}

		private boolean shouldKeep(MilitarySexualTrauma obj) {
			// return (super.shouldKeep((ClinicalDetermination)obj));
			return ((obj.getStatus() != null));
		}

		private void transfer(MilitarySexualTrauma input,
				MilitarySexualTraumaMetaData metaData) throws BuilderException {
			super.transfer((ClinicalDetermination) input, metaData);

			input.setStatus(this.buildStatus(input.getStatus(), metaData
					.getStatus()));
			input.setStatusChangeDate(super.build(input.getStatusChangeDate(),
					metaData.getStatusChangeDate()));
		}
	}

	public static class NoseThroatRadiumBuilder extends
			ClinicalDeterminationBuilder {
		/**
		 * An instance of serialVersionUID
		 */
		private static final long serialVersionUID = 766963650608158204L;

		private Builder verificationMethodBuilder;

		public NoseThroatRadiumBuilder() {
			super();
		}

		public Builder getVerificationMethodBuilder() {
			return this.verificationMethodBuilder;
		}

		public void setVerificationMethodBuilder(Builder verificationMethodBuilder) {
			this.verificationMethodBuilder = verificationMethodBuilder;
		}

		public NoseThroatRadium build(NoseThroatRadiumMetaData metaData)
				throws BuilderException {
			NoseThroatRadium input = metaData.getEntity();
			NoseThroatRadium output = (input == null) ? new NoseThroatRadium()
					: input;

			this.transfer(output, metaData);

			return this.shouldKeep(output) ? output : null;
		}

		private NTRVerificationMethod buildVerificationMethod(
				NTRVerificationMethod input, String code) throws BuilderException {
			return super.shouldDelete(code) ? null : (NTRVerificationMethod) super
					.build(this.verificationMethodBuilder, input, code);
		}

		private boolean shouldKeep(NoseThroatRadium obj) {
			// return (super.shouldKeep((ClinicalDetermination)obj));
			return ((obj.getVerificationDate() != null));
		}

		private void transfer(NoseThroatRadium input,
				NoseThroatRadiumMetaData metaData) throws BuilderException {
			super.transfer((ClinicalDetermination) input, metaData);

			input.setDiagnosedWithCancer(super.build(input
					.getDiagnosedWithCancer(), metaData.getDiagnosedWithCancer()));
			input.setFromAviatorServiceBefore1955(super.build(input
					.isFromAviatorServiceBefore1955(), metaData
					.getFromAviatorServiceBefore1955()));
			input.setFromSubmarinerServiceBefore1965(super.build(input
					.isFromSubmarinerServiceBefore1965(), metaData
					.getFromSubmarinerServiceBefore1965()));
			input.setReceivingTreatment(super.build(input.getReceivingTreatment(),
					metaData.getReceivingTreatment()));
			input.setVerificationDate(super.build(input.getVerificationDate(),
					metaData.getVerificationDate()));
			input.setVerificationFacility(super.build(input
					.getVerificationFacility(), metaData.getVerificationFacility()));
			input.setVerificationMethod(this.buildVerificationMethod(input
					.getVerificationMethod(), metaData.getVerificationMethod()));
		}
	}

    public static class SpinalCordInjuryBuilder extends
            ClinicalDeterminationBuilder {
        /**
         * An instance of serialVersionUID
         */
        private static final long serialVersionUID = 3061779410870790812L;

        private Builder typeBuilder;

        public SpinalCordInjuryBuilder() {
            super();
        }

        public Builder getTypeBuilder() {
            return this.typeBuilder;
        }

        public void setTypeBuilder(Builder typeBuilder) {
            this.typeBuilder = typeBuilder;
        }

        public SpinalCordInjury build(SpinalCordInjuryMetaData metaData)
                throws BuilderException {
            SpinalCordInjury input = metaData.getEntity();

            SpinalCordInjury output = (input == null) ? new SpinalCordInjury()
                    : input;

            this.transfer(output, metaData);

            return this.shouldKeep(output) ? output : null;
        }

        private SpinalCordInjuryType buildType(SpinalCordInjuryType input,
                String code) throws BuilderException {
        	code = ("".equals(code)) ? SpinalCordInjuryType.CODE_NOT_APPLICABLE.getCode() : code;

        	return (SpinalCordInjuryType) super.build(this.typeBuilder, input,
                    code);
        }

        private boolean shouldKeep(SpinalCordInjury obj) {
            // return (super.shouldKeep((ClinicalDetermination)obj));
            return ((obj.getSpinalCordInjuryType() != null));
        }

        private void transfer(SpinalCordInjury input,
                SpinalCordInjuryMetaData metaData) throws BuilderException {
            super.transfer((ClinicalDetermination) input, metaData);

            input.setSpinalCordInjuryType(this.buildType(input
                    .getSpinalCordInjuryType(), metaData.getType()));
        }

    }

}