/**
   @file ms_envelope.sas
   @brief This macro uses data from the SDD to recode non-inpatient encounters to inpatient if they were determined to have occurred during an inpatient stay.

   @details
	- Extract IP encounters (occuring after &mindate. when specified)
	- Remove encounter ids to delete if required
	- Collapse IP encounters into IP episodes to reduce number of observations involved in joining datasets.	
	- For each record in INFILE within an inpatient stay, recode encounter type as inpatient if not already coded as such.

   @par Program inputs
	- &ENCOUNTERINFILE. (Dataset with encounter data.)
	- &INFILE. (Dataset with diagnosis/procedure claims data.)

   @par Program outputs
	- &OUTFILE. (Dataset with reclassified claims.)

* **Usage**

	  %ms_envelope(INFILE=worktemp.meds,
                   ENCOUNTERINFILE=indata.&ENCTABLE.,
				   MINDATE=&studystartdate,
                   OUTFILE=worktemp.meds);
    
   @param [in] INFILE Name of SAS dataset with diagnosis and/or procedure claims data.   			  
   @param [in] ENCOUNTERINFILE Name of SAS dataset with encounter data.	
   @param [in] MINDATE Extract all claims occuring on or after this date. 
   @param [out] OUTFILE Name of output file with reclassified claims.

<h4> SAS Macros Dependencies </h4>
   @li ms_delencounterids.sas

   @note This operation is done without using the ENCOUNTERID variable, as this variable can be inconsistent across data partner datasets.
 
   @author Sentinel Coordinating Center (info@sentinelsystem.org)
**/

%macro MS_ENVELOPE(INFILE=,ENCOUNTERINFILE=,MINDATE=,OUTFILE=);       

%put =====> MACRO CALLED: ms_envelope;

	*Reclassification as inpatient all selected claims within admission and discharge dates of an inpatient stay;
	*Get Unique ADate-Ddate combinations;
	proc sort nodupkey data=&ENCOUNTERINFILE.(keep=PatId Adate Ddate EncType %if %str(&ENCIDTOEXCLUDE.) ne %str() %then %do; encounterid %end; 
											  where=(EncType='IP' %if %str("&mindate") ne %str("") %then %do; and max(Adate, Ddate) >= &mindate. %end;)) 
	                 out=_IPdates(keep=PatId Adate Ddate %if %str(&ENCIDTOEXCLUDE.) ne %str() %then %do; encounterid %end;);
	by PatId Adate Ddate;
	run;     

	*Delete data for encounterids in DPs &ENCIDTOEXCLUDE. files;
	%ms_delencounterids(datafile=_IPdates,
                        EncIdsfile=&ENCIDTOEXCLUDE.,
                        Outfile=_IPdates);

	%if &run_envelope. = 0 %then %do;
		%let sign = %str(<=);

		* Many consecutive single day encounters can be present for a patient in _IPDates. For efficiency purposes, 
		  collapse IP encounters into IP episodes considering a 0 day gap to reduce the number of observations before joining with &INFILE.;
		data _IPdates;
		set  _IPdates %if %str(&ENCIDTOEXCLUDE.) ne %str() %then %do; (drop=encounterid) %end;;
		by PatId Adate;
		length IP_episode 3;
		if Adate - max(lag(Adate),lag(Ddate))-1 > 0 then IP_episode=IP_episode+1; 		
		if first.Patid then IP_episode=1;
		if missing(Ddate) then Ddate=Adate;
		retain IP_episode;
		run;

		proc sql noprint undo_policy=none;
		create table _IPdates as
		select PatId,
	           min(adate) as IP_Adate format=mmddyy10. length=4,
		  	   max(ddate) as IP_Ddate format=mmddyy10. length=4
		from _IPdates  
		group by Patid, IP_episode;
		quit;		
	%end;
	%else %do;
		%let sign = %str(<); 

		proc datasets nowarn nolist lib=work;
		modify _IPdates;
		rename adate = IP_Adate;
		rename ddate = IP_Ddate;
		quit;
	%end;
		
	*For each record in &INFILE within an inpatient stay, recode encounter type as inpatient if not already coded as such;
	data &OUTFILE.;
		if 0 then set _IPdates(keep=PatId IP_Adate IP_DDate);
		declare hash h(dataset:"_IPdates",HASHEXP:16, multidata:"Y");
		h.definekey('PatId');
		h.definedata('IP_Adate', 'IP_DDate');
		h.definedone();

		do until (eof);
			set &INFILE. end=eof;	
			drop IP_:;
			
			if h.num_items>0 then do;
				rc = h.find();
				do while (rc = 0);
					if EncType ne 'IP' and IP_ADate &sign. ADate <=  max(IP_ADate,IP_DDate) then do;
						pdx='X';
    	    			EncType='IP'; 						
					end;
				 	rc = h.find_next();
				end;
				drop rc;
			end;	
			output;	
		end;		
	run;

	proc datasets library = work nolist nowarn nodetails;
	delete _IPDates;
	quit;       

%put NOTE: ******** END OF MACRO: ms_envelope ********;

%mend MS_ENVELOPE;