****************************************************************************************************
*                                           PROGRAM OVERVIEW
****************************************************************************************************
*
* PROGRAM: codedistribution_output.sas  
* Created (mm/dd/yyyy): 04/16/2021
*
*--------------------------------------------------------------------------------------------------
* PURPOSE: The macro creates both the Full Code Distribution and Total Code Counts output
*                                        
*  Program inputs:                                                                                   
* 
*  Program outputs:                                                                                                                                       
*
*  PARAMETERS:                                                                       
*            
*  Programming Notes:                                                                                
*                                                                           
*
*--------------------------------------------------------------------------------------------------
* CONTACT INFO: 
*  Sentinel Coordinating Center
*  info@sentinelsystem.org
*
***************************************************************************************************;

%macro codedistribution_output;
	 
	/* This macros produces output for a specific distribution type (EXP or HOI) */
	%macro codedistribution_type(distindextype=);
		/* Compute group label to display in title */
		%let grouplabel=;
		%isdata(dataset=labelfile);
    	%if %eval(&nobs>0) %then %do;
			proc sql noprint;
			select label into :grouplabel trimmed from labelfile
			where lower(group)="&group." and runid = "&runid" and
			%if &distindextype. eq exp %then %do;
				lower(labeltype)="grouplabel";
			%end;
			%else %do;
				lower(labeltype)="outcomelabel";
			%end;
			quit;
		%end;

		%if %str("&grouplabel.") eq %str("") %then %let grouplabel = %trim(&group.);

		/* Compute Total Code Counts (must be processed first to restrict to topncodedist */		
		proc sort data=codedistdata (where=(lower(group) = "&group." and runid = "&runid" and lower(distindextype) = "&distindextype."))
			 out=codedistcounts (keep = runid distindexlist code description codetype codecat codetype totalN);
		by distindexlist descending totalN code;
		run;

		data codedistcounts; 
		set codedistcounts;
		by distindexlist descending totalN code;
		if first.distindexlist then do;
			codeCount = TotalN;
		end;
		retain codeCount;
		else do;
			codeCount = codeCount;
		end;
		run;

		proc sql noprint undo_policy = none;
		create table codedistcounts as 
		select  distinct code 
				,description 
				,codecat 
				,codetype Label="Code Type"
				,sum(codeCount) as N
		from codedistcounts
		group by code, description, codecat, codetype
		order by N desc;
		quit;

		data codedistcounts;
		set codedistcounts;
		if _N_ <= &topncodedist.;
		run;
		

		/*  Compute and output Full Code Distribution */
		%tableletter();

		proc sql;
		create table repdata.table&tablenum.&tableletter as 
		select  dist.group
				,dist.distindexlist
				,dist.code Label="Code"
				,dist.description Label="Code Description"
				,dist.codecat Label="Code Category"
				,dist.codetype Label="Code Type"
				,dist.caresetting Label="Encounter Care Setting"
				,dist.totalN as totalN Label="Overall Counts"
		from codedistdata (where=(lower(group) = "&group." and runid = "&runid" and lower(distindextype) = "&distindextype.")) as dist
		join codedistcounts as code
			on dist.codecat=code.codecat 
			and dist.codetype=code.codetype 
			and dist.code=code.code
		order distindexlist, code;
		quit;

		data repdata.table&tablenum.&tableletter;
		length caresetting codetype codecat code $200 description $700;
		set repdata.table&tablenum.&tableletter (rename = 
						                (code = _code 
						                 caresetting = _caresetting 
						                 TotalN = _TotalN
						                 description = _description
						                 codetype = _codetype
						                 codecat = _codecat));
		by distindexlist;
		if first.distindexlist then do;
			caresetting = '';
			TotalN = 0;
			code = '';
			description = '';
			codecat = '';
			codetype = '';
		end;

		TotalN + _TotalN;
		caresetting = cat(strip(_caresetting), '^n', caresetting);
		code = cat(strip(_code), '^n', code);
		description = cat(strip(_description), '^n', description);
		codecat = cat(strip(_codecat), '^n', codecat);
		codetype = cat(strip(_codetype), '^n', codetype);
		retain caresetting code description codecat codetype;

		if last.distindexlist then do;
			caresetting = substr(caresetting,1,length(strip(caresetting)) - 2);
			description = substr(description,1,length(strip(description)) - 2);
			codetype = substr(codetype,1,length(strip(codetype)) - 2);
			codecat = substr(codecat,1,length(strip(codecat)) - 2);
			code = substr(code,1,length(strip(code)) - 2);
			row_separator + 1;
			output; 
		end;
		run;

		proc sort data=repdata.table&tablenum.&tableletter(drop = _:);
		by descending totalN;
		run; 
	

		%let title = %quote(Table &tablenum.&tableletter.. Full Code Distribution of &grouplabel. in the &database. from &startdateformatted. to &enddateformatted.);

		ods escapechar="^";
        %if &destination = excel %then %do;
        ods excel options(sheet_name="Table &tablenum.&tableletter." tab_color="teal");
        %end;
        ods proclabel = "Table &tablenum.&tableletter.";

		proc report data=repdata.table&tablenum.&tableletter nofs nowd spanrows missing split='*'
        		style(header)=[rules=none vjust=b frame=void background=BGR borderleftcolor = BGR]
        		style(report)=[rules=none frame=void cellpadding =1.75pt];

		column distindexlist code description codecat codetype totalN caresetting row_separator;
        define distindexlist / noprint;
		define row_separator / analysis noprint;
        define code / display 'Code'  
        	style(column)=[just=L tagattr="type:String" width=20%] 
            style(header)=[just=L background = bgr borderleftcolor = BGR];
        define description / display 'Code Description'  
          	style(column)=[just=c tagattr="type:String" width=30%] 
            style(header)=[just=c background = bgr borderleftcolor = BGR];
        define codecat / display 'Code Category'  
          	style(column)=[width=.7in just=c tagattr="type:String"] 
            style(header)=[just=c background = bgr borderleftcolor = BGR];
        define codetype / display 'Code Type' 
          	style(column)=[width=.7in just=c tagattr="type:String"] 
            style(header)=[just=c background = bgr borderleftcolor = BGR];
        define totalN / display 'Overall Counts' format=comma10.0
          	style(column)=[width=.7in just=c vjust=c] 
            style(header)=[just=c background = bgr borderleftcolor = BGR];
        define caresetting / display 'Encounter Care Setting'  
          	style(column)=[width=.7in just=c] 
            style(header)=[just=c background = bgr borderleftcolor = BGR];

		/* Add title */
		compute before _page_ / style=[background=white font_weight=bold just=L foreground=black vjust=b bordertopcolor=white 
		                               borderbottomwidth=&bordersize tagattr="wrap:yes" nobreakspace=off cellheight=.3in];
        line "&title.";
        endcomp;

		compute row_separator;
		call define (_row_,'style','style=[borderbottomcolor=lightgrey borderbottomwidth=.5pt] ' );
		endcomp;

        compute after _page_ / style=[bordertopcolor=black bordertopwidth=&bordersize borderbottomcolor=white borderleftcolor=white borderrightcolor=white];
        line ' ';
        endcomp;

      	run;
	    

		/* Output Total Code Counts */
		%tableletter();

		data repdata.table&tablenum.&tableletter;
		set codedistcounts;		
		run;		
	

		%let title = %quote(Table &tablenum.&tableletter.. Total Code Counts of &grouplabel. in the &database. from &startdateformatted. to &enddateformatted.);

		ods escapechar="^";
        %if &destination = excel %then %do;
        ods excel options(sheet_name="Table &tablenum.&tableletter." tab_color="teal");
        %end;
        ods proclabel = "Table &tablenum.&tableletter.";

		proc report data=repdata.table&tablenum.&tableletter nofs nowd spanrows missing split='*'
        	style(header)=[rules=none vjust=b frame=void background=BGR borderleftcolor = BGR]
        	style(report)=[rules=none frame=void cellpadding =1.75pt];

		column code description codecat codetype N  ;
	    define code / display 'Code' group  order order= data 
	      	style(column)=[just=L tagattr="type:String" width=20%] 
            style(header)=[just=L background = bgr borderleftcolor = BGR];
	    define description / display 'Code Description'  group  order order= data 
	      	style(column)=[just=c tagattr="type:String" width=30%] 
            style(header)=[just=c background = bgr borderleftcolor = BGR];
	    define codecat / display 'Code Category'  group  order order= data 
	      	style(column)=[width=.7in just=c tagattr="type:String"] 
            style(header)=[just=c background = bgr borderleftcolor = BGR];
	    define codetype / display 'Code Type' group  order order= data 
	      	style(column)=[width=.7in just=c tagattr="type:String"] 
            style(header)=[just=c background = bgr borderleftcolor = BGR];
	    define N / display 'Overall Counts' group order order= data format=comma10.0
	      	style(column)=[width=.7in just=c] 
            style(header)=[just=c background = bgr borderleftcolor = BGR];

		/* Add title */
		compute before _page_ / style=[background=white font_weight=bold just=L foreground=black vjust=b bordertopcolor=white 
		                               borderbottomwidth=&bordersize tagattr="wrap:yes" nobreakspace=off cellheight=.3in];
        line "&title.";
        endcomp;
        compute after _page_ / style=[bordertopcolor=black bordertopwidth=&bordersize borderbottomcolor=white borderleftcolor=white borderrightcolor=white];
        line ' ';
        endcomp;

      	run;

	%mend codedistribution_type;
 

    %let tablecount=1;
    
	proc sql noprint;
	select count(*) into :numgroupscodedist trimmed 
	from GroupsDist;
	quit;
	
    %do loopcount = 1 %to &numgroupscodedist.; 

		%let codedistexp = N;
		%let codedisthoi = N;

        data _null_;
            set GroupsDist;
			if &loopcount. = _N_;
            call symputx('runid', runid);
            call symputx('group', group);	
			if missing(topncodedist) then call symputx('topncodedist',25);
		  	else call symputx('topncodedist',topncodedist);	
            if index(upcase(codedist), "EXP") > 0 then call symputx('codedistexp', 'Y');
			if index(upcase(codedist), "HOI") > 0 then call symputx('codedisthoi', 'Y');
        run;
				
		%if &codedistexp. eq Y %then %do;
			* Defensive: make sure the requested data is available;
			%let obscount=0;

			proc sql noprint;
			select count(*) into :obscount from codedistdata
			where lower(group) = "&group." and runid = "&runid" and lower(distindextype) = "exp";
			quit;

			%if %eval(&obscount. > 0) %then %codedistribution_type(distindextype=exp);
		%end;
		%if &codedisthoi. eq Y %then %do;
			* Defensive: make sure the requested data is available;
			%let obscount=0;

			proc sql noprint;
			select count(*) into :obscount from codedistdata
			where lower(group) = "&group." and runid = "&runid" and lower(distindextype) = "hoi";
			quit;

			%if %eval(&obscount. > 0) %then %codedistribution_type(distindextype=hoi);
		%end;

	%end; *numgroupscodedist;
		
%mend codedistribution_output;