package gov.va.med.esr.messaging.builder.message;

import java.util.List;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;


import gov.va.med.fw.hl7.builder.HL7MetaData;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.util.builder.BuilderException;

import gov.va.med.esr.common.model.lookup.MessageType;
import gov.va.med.esr.common.model.lookup.MonetaryBenefitType;
import gov.va.med.esr.common.model.messaging.SiteIdentity;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.service.SystemParameterService;

/**
 * @author Rajiv Patnaik Created on Dec 22, 2005
 * @version 1.0 Copyright © 2005 VHA. All rights reserved
 */
public class AbstractZ11Builder extends AbstractMessageBuilder {

   /**
    * An instance of serialVersionUID
    */
   private static final long serialVersionUID = 5610092785179377200L;

   private ZPDBuilder zpdBuilder;

   private ZIEBuilder zieBuilder;

   private ZIOBuilder zioBuilder;

   private ZELBuilder zelBuilder;

   private ZENBuilder zenBuilder;

   private ZMTBuilder zmtBuilder;

   private ZCDBuilder zcdBuilder;

   private ZSPBuilder zspBuilder;

   private ZMHBuilder zmhBuilder;

   private ZRDBuilder zrdBuilder;

   private OBXBuilder obxBuilder;

   private ZE2Builder ze2Builder;

   private ZHPBuilder zhpBuilder;  //CCR12064

   /**
    * An instance of systemParameterService
    */
   private SystemParameterService systemParameterService = null;



   public SystemParameterService getSystemParameterService() {
	   return systemParameterService;
   }

   public void setSystemParameterService(
		   SystemParameterService systemParameterService) {
	   this.systemParameterService = systemParameterService;
   }

   /**
    * @return Returns the obxBuilder.
    */
   public OBXBuilder getObxBuilder() {
      return obxBuilder;
   }

   /**
    * @param obxBuilder
    *           The obxBuilder to set.
    */
   public void setObxBuilder(OBXBuilder obxBuilder) {
      this.obxBuilder = obxBuilder;
   }

   /**
    * @return Returns the zcdBuilder.
    */
   public ZCDBuilder getZcdBuilder() {
      return zcdBuilder;
   }

   /**
    * @param zcdBuilder
    *           The zcdBuilder to set.
    */
   public void setZcdBuilder(ZCDBuilder zcdBuilder) {
      this.zcdBuilder = zcdBuilder;
   }

   /**
    * @return Returns the zelBuilder.
    */
   public ZELBuilder getZelBuilder() {
      return zelBuilder;
   }

   /**
    * @param zelBuilder
    *           The zelBuilder to set.
    */
   public void setZelBuilder(ZELBuilder zelBuilder) {
      this.zelBuilder = zelBuilder;
   }

   /**
    * @return Returns the zenBuilder.
    */
   public ZENBuilder getZenBuilder() {
      return zenBuilder;
   }

   /**
    * @param zenBuilder
    *           The zenBuilder to set.
    */
   public void setZenBuilder(ZENBuilder zenBuilder) {
      this.zenBuilder = zenBuilder;
   }

   /**
    * @return Returns the zieBuilder.
    */
   public ZIEBuilder getZieBuilder() {
      return zieBuilder;
   }

   /**
    * @param zieBuilder
    *           The zieBuilder to set.
    */
   public void setZieBuilder(ZIEBuilder zieBuilder) {
      this.zieBuilder = zieBuilder;
   }

   /**
    * @return Returns the zioBuilder.
    */
   public ZIOBuilder getZioBuilder() {
      return zioBuilder;
   }

   /**
    * @param zioBuilder
    *           The zioBuilder to set.
    */
   public void setZioBuilder(ZIOBuilder zioBuilder) {
      this.zioBuilder = zioBuilder;
   }

   /**
    * @return Returns the zmhBuilder.
    */
   public ZMHBuilder getZmhBuilder() {
      return zmhBuilder;
   }

   /**
    * @param zmhBuilder
    *           The zmhBuilder to set.
    */
   public void setZmhBuilder(ZMHBuilder zmhBuilder) {
      this.zmhBuilder = zmhBuilder;
   }

   /**
    * @return Returns the zmtBuilder.
    */
   public ZMTBuilder getZmtBuilder() {
      return zmtBuilder;
   }

   /**
    * @param zmtBuilder
    *           The zmtBuilder to set.
    */
   public void setZmtBuilder(ZMTBuilder zmtBuilder) {
      this.zmtBuilder = zmtBuilder;
   }

   /**
    * @return Returns the zpdBuilder.
    */
   public ZPDBuilder getZpdBuilder() {
      return zpdBuilder;
   }

   /**
    * @param zpdBuilder
    *           The zpdBuilder to set.
    */
   public void setZpdBuilder(ZPDBuilder zpdBuilder) {
      this.zpdBuilder = zpdBuilder;
   }

   /**
    * @return Returns the zrdBuilder.
    */
   public ZRDBuilder getZrdBuilder() {
      return zrdBuilder;
   }

   /**
    * @param zrdBuilder
    *           The zrdBuilder to set.
    */
   public void setZrdBuilder(ZRDBuilder zrdBuilder) {
      this.zrdBuilder = zrdBuilder;
   }

   /**
    * @return Returns the zspBuilder.
    */
   public ZSPBuilder getZspBuilder() {
      return zspBuilder;
   }

   /**
    * @param zspBuilder
    *           The zspBuilder to set.
    */
   public void setZspBuilder(ZSPBuilder zspBuilder) {
      this.zspBuilder = zspBuilder;
   }

   /**
    * @return Returns the zspBuilder.
    */
   public ZE2Builder getZe2Builder() {
      return ze2Builder;
   }

   /**
    * @param zspBuilder
    *           The zspBuilder to set.
    */
   public void setZe2Builder(ZE2Builder ze2Builder) {
      this.ze2Builder = ze2Builder;
   }

   /**
    * Builds segments common to ORUZ11 and ORFZ11
    *
    * @param segments
    * @param person
    * @param siteIdentity
    * @return
    * @throws BuilderException
    */
   public List buildCommonZ11Segments(List segments, Person person,
         SiteIdentity siteIdentity) throws BuilderException {

      try {
         HL7MetaData metaData = new HL7MetaData(person);

         segments.add(super.buildPIDSegment(person, siteIdentity));
         segments.add(this.zpdBuilder.build(metaData));
         segments.add(this.zieBuilder.build(metaData));
         segments.add(this.zioBuilder.build(metaData));

         // Build ZEL segments - repeatable
         //get system parameter to check which destination should include CL-V data
         String vistACLRollout = systemParameterService.getCLVistARolloutStr();
         Set<String> selectedCLInstallSites = new HashSet<String>();

         if (vistACLRollout.contains(",")){
        	 StringTokenizer sitesTokenizer = new StringTokenizer(vistACLRollout, ",");
        	 while (sitesTokenizer.hasMoreTokens()) {
      			String selectedSite = sitesTokenizer.nextToken();
      			if (selectedSite != null) {
      				selectedSite = selectedSite.trim();
     				if (selectedSite.equals("")) {
     					selectedSite = null;
     				}
     			}

     			if (selectedSite != null) {
     				selectedCLInstallSites.add(selectedSite.toUpperCase());
     			}
        	 }
         }
         else if ((vistACLRollout != null) && (vistACLRollout.length() > 0))
        	 selectedCLInstallSites.add(vistACLRollout.toUpperCase());

         boolean includeCLData = false;
         if( vistACLRollout.equalsIgnoreCase("ALL") || selectedCLInstallSites.contains(siteIdentity.getVaFacility().getStationNumber())) {
        	 includeCLData = true;
         }

         List zelSegments = null;
         zelSegments = (List)this.zelBuilder.build(metaData,includeCLData);


         for( int i = 0; i < zelSegments.size(); i++ ) {
            segments.add(zelSegments.get(i));
         }


         if(this.getSystemParameterService().getVBADataSharingIndicator()){
        	 if (person.getMonetaryBenefitAward() != null
 					&& person.getMonetaryBenefitAward()
 							.getMonetaryBenefitByType(
 									MonetaryBenefitType.CODE_VA_PENSION) != null
 					&& person.getMonetaryBenefitAward()
 							.getMonetaryBenefitByType(
 									MonetaryBenefitType.CODE_VA_PENSION)
 							.getPension() != null) {
 				List ze2Segments = (List) this.ze2Builder.build(metaData);
 				for (int i = 0; i < ze2Segments.size(); i++) {
 					segments.add(ze2Segments.get(i));
 				}
 			}

         }

         // CCR12064 Build ZHP segments - repeatable
         // WI 261661, remove parameter check, HBP sharing fully active now forever
         	  //if (this.getSystemParameterService().getHBPDataSharingIndicator()!= null && this.getSystemParameterService().getHBPDataSharingIndicator()) {
					List zhpSegments = (List) this.zhpBuilder.build(metaData);
					for (int i = 0; i < zhpSegments.size(); i++) {
						segments.add(zhpSegments.get(i));
					}
			  //}


         segments.add(this.zenBuilder.build(metaData));

         // For ORUZ11, the ZMT Builder returns a List containing 1 ZMT
         // segment
         ZMTMetaData zmtMetadata = new ZMTMetaData(person, getLookupService()
               .getMessageTypeByCode(MessageType.CODE_ORUZ11_TO_SITE.getName()));
         List zmtSegments = (List)this.zmtBuilder.build(zmtMetadata);
         segments.add(zmtSegments.iterator().next());

         // Build ZCD segments - repeatable
         List zcdSegments = (List)this.zcdBuilder.build(metaData);
         for( int i = 0; i < zcdSegments.size(); i++ ) {
            segments.add(zcdSegments.get(i));
         }

         segments.add(this.zspBuilder.build(metaData, siteIdentity));

         // Build ZMH segments - repeatable
         List zmhSegments = (List)this.zmhBuilder.build(metaData);
         for( int i = 0; i < zmhSegments.size(); i++ ) {
            segments.add(zmhSegments.get(i));
         }

         // Build ZRD segments - repeatable
         List zrdSegments = (List)this.zrdBuilder.build(metaData);
         for( int i = 0; i < zrdSegments.size(); i++ ) {
            segments.add(zrdSegments.get(i));
         }

         // Build OBX segments - repeatable
         List obxSegments = (List)this.obxBuilder.build(metaData);
         for( int i = 0; i < obxSegments.size(); i++ ) {
            segments.add(obxSegments.get(i));
         }
      }
      catch( ServiceException me ) {
         throw new BuilderException(
               "Failed to build ORUZ11 message due to an exception ", me);
      }

      return segments;
   }

public ZHPBuilder getZhpBuilder() {
	return zhpBuilder;
}

public void setZhpBuilder(ZHPBuilder zhpBuilder) {
	this.zhpBuilder = zhpBuilder;
}

}