*!v2.00 Paper Out
*v1.77 Allows Anticipation
*v1.76 Excludes Fixed variables from the interactions with Cohort
*v1.75 May allow for Intervalled Event
*v1.71  Better Hettype
*v1.7  Adds Event Hettype. Also allows to use Characteristics as is, or demean.
* Further Panel Data Corrections
* v1.65 Adds restrictions to Heterogeneity of Treatment Effect time / cohort
* v1.6  FEVAR: Allows Interactions
* v1.52 Minor Bug. No coeff if not existent
* v1.51 Addressed Bug when there is no never treated (but using never)
* v1.5  Multiple Methods plus extra
* some options not yet documented
* v1.42 Fixes Bug with Continuous Trt
* v1.41 Allows for multiple Options
*       Also FV and TS
* v1.4  Allows for TRT to be continuous, and adds example
* v1.36 Adds TrtVar or Gvar
* v1.35 Adds method for margins
* v1.34 Minor Improv to Combinations. Also only works St15 or above
* v1.33 reduces ammount of ommited empty
* v1.32 Corrects for bug with no ivar
* v1.31 Corrects for Never group
* v1.3 Corrects for Nonlinear models
* 8/30/2022 corrects for long variables
* v1.2 FRA 8/17/2022 Adds Correction unbalanced panel
* v1.1 FRA 8/5/2022 Redef not yet treated.
* v1   FRA 8/5/2022 Has almost everything we need
****
* Add to estat event, an option for Any ATTGT
* This means, a way to do simple, for post and pre..algo como el cevent. But based on Everything
* This version aims to incorporate features for Gravity

*** Incorporar Intensidad con dos tratamientos para Gravity. bi ffects

program jwdid_example
	preserve
	frause mpdta, clear
	display "jwdid lemp, ivar(countyreal) tvar(year) gvar(first) never"
	jwdid lemp, ivar(countyreal) tvar(year) gvar(first) never
	display "estat simple"
	estat simple
	display "estat calendar"
	estat calendar
	display "estat group"
	estat group
	display "estat event"
	estat event
	restore
end

program method_parser, rclass
	syntax namelist , [*]
	local method1:word 1 of `namelist'
	return local method `namelist'
	return local method1 `method1'
	return local options `options'
end

program check_install, rclass
	syntax [namelist]
	foreach i in reghdfe hdfe `namelist' {
		capture which `i'
		if _rc!=0 {
			display in red as error "You need to install `i' from SSC"
			error 198
		}
	}
end

program parse_hettype, rclass
    syntax anything, [ll(numlist max =1) ul(numlist max=1) * ]

    if ("`ll'"!="") & ("`ul'"!="") {
        if `ll'>=`ul' {
            display as err "ll() has to be smaller than ul()"
            error 911
        }
    }

    return local hettype `anything'
    return local ll `ll'
    return local ul `ul'
end

program parse_hettype_evco, rclass
    syntax anything,  evbase(numlist max=1) erecode(string asis) [* ]
    tempvar aux
    ren __evnt__ `aux'
    recode `aux' `erecode', gen(__evnt__)
    return local evbase = `evbase'

end

** Gets list of variables
program getvarlist, rclass
    syntax varlist (fv ts)
    ** First Get varlist
    fvexpand `varlist'
    local vlist = subinstr("`r(varlist)'","."," ",.)
    local vlist = subinstr("`vlist'","#"," ",.)
    novarabbrev {
        foreach i of local vlist {
            capture confirm numeric var `i'
            if _rc ==0 {
                local vvlist `vvlist' `i'

            }

        }
    }
    ** Keep nonrepeating ones
    mata: a=tokens("`vvlist'");a=uniqrows(a')';st_local("vvlist",invtokens(a))
    return local varlist `vvlist'
end

**  Small program to check fix vars
mata:
    void mt_fixvar(string scalar xvarname, string scalar touse){
        // Load all data
        xvar = st_data(.,xvarname,touse)
        // sort and PanelStup
        xvar=xvar[order(xvar[,1],1) ,]
        // panel
        info = panelsetup(xvar,1)
        // sort across all variables
        for(i=2;i<=cols(xvar);i++)    xvar[,i]=xvar[order(xvar[,(1,i)],(1,2)),i]
        // verify if Variables change
        csum =colsum(xvar[info[,2],]:-xvar[info[,1],])
        toret1 = invtokens(select(tokens(xvarname), csum ))
        toret2 = invtokens(select(tokens(xvarname),!csum ))
        st_global("r(xvarvar)",toret1)
        st_global("r(xvarcons)",toret2)
    }
end

program is_x_fix, rclass
    syntax varlist(fv ts) [if], ivar(varname)
    ** Expand Interactions
    marksample touse
    ms_fvstrip `varlist', expand dropomit
    local evarlist `r(varlist)'
    ** ID original variables
    getvarlist `varlist'
    local xvarlist `r(varlist)'
  fvset base none `xvarlist '
    mata:mt_fixvar("`ivar' `evarlist '","`touse'")
  fvset base default `xvarlist'

end

program jwdid, eclass
	** Error with 14 or earlier
	version 15
	** Replay
	syntax [ anything(everything)] [in] [pw iw aw], [example *]
	if replay() {
		if "`example'" !="" {
			jwdid_example
		}
		else {
			if "`e(cmd)'"=="jwdid" ereturn display
			else display "Last estimation not found"
		}
		exit
	}

	syntax varlist( fv ts) [if] [in] [pw iw aw],  [  Ivar(varname)  cluster(varlist) ] ///
								  [Tvar(varname) time(varname)   fevar(varlist fv ts)] /// fevar for other Fixed effects Valid for reghdfe and pmlhdfe
								  [Gvar(varname) trtvar(varname) trgvar(varname)] ///
								  [never group method(string asis) corr  ] ///
								  [hettype(string asis) * ]    ///
								  [exovar(varlist fv ts) exogvar(varlist fv ts) ]  /// Variables not to be interacted with Gvar Tvar Treatment
                                  [xtvar(varlist fv ts) ]  /// Variables interacted with  Tvar
                                  [xgvar(varlist fv ts) ]  /// Variables interacted with Gvar
								  [xasis ] ///
								  [ANTIcipation(numlist max=1 >0) ] // Allows for Anticipation

	// For Gravity
	// Anticipation is the number of periods before the event
	// Default is 1 (so g-1 is the excluded period)
	if "`anticipation'"=="" local anti 1
	else local anti `anticipation'

	if "`method'"!="" {
		method_parser `method'
		local method `r(method)'
		local method1 `r(method1)'
		local method_option `r(options)'
	}
	** Does not matter if one uses Exovar or Exogvar. Same thing
	local exogvar `exovar' `exogvar'

	if "`hettype'"=="" local hettype timecohort

    parse_hettype `hettype'
    local ehettype `r(hettype)'
    local rll     `r(ll)'
    local rul     `r(ul)'

	if !inlist("`ehettype'","time","cohort","timecohort","event","eventcohort","twfe") {
		display in red "hettype must be time, cohort, or timecohort"
		error 198
	}
    if "`ehettype'"=="eventcohort" local never never
	// Check installation
	check_install `method'

	marksample  touse
	markout    `touse' `ivar' `tvar' `gvar'
	gettoken y x:varlist
	// y dep variable
	// x indep in Jwdid y xs
	if "`tvar'`time'"=="" {
		display in red "option time/tvar() required"
		error 198
	}
	if "`tvar'"=="" local tvar `time'

	if "`gvar'`trtvar'"=="" {
		display in red "option gvar/trtvar() required"
		error 198
	}

	if "`trtvar'`gvar'"=="" {
		display as error "Cohort variable not specified"
		error 198
	}
	else if "`trtvar'"!="" & "`gvar'"!="" {
		display as error "You can only specify gvar or trtvar. Not both"
		error 198
	}
	else if "`trtvar'"!="" {
		capture drop __gvar
		qui:_gjwgvar __gvar=`trtvar', tvar(`tvar') ivar(`ivar')
		local gvar __gvar
	}
	// Groups refer to Gvar. Not compatible if not panel
	if "`ivar'"=="" local group group
	if "`method'"!="" & "`method'"!="ppmlhdfe" {
		local group group
	}
	// ID Time Fixed Variables
	local xvarvar `x'

 	if "`ivar'"!="" & "`group'"=="" & "`x'"!="" {
		is_x_fix `x' if `touse', ivar(`ivar')
		local xvarcons  `r(xvarcons)'
		local xvarvar   `r(xvarvar)'

	}

 	*easter_egg
	** Count gvar
	/*qui:count if `gvar'==0 & `touse'==1
	if `r(N)'==0 {
		*qui:sum `gvar' if `touse'==1 , meanonly

	}*/

	** Exclude of sample units that have always been treated.
	tempvar tvar2
	qui:bysort `touse' `ivar': egen long `tvar2'=min(`tvar')
	qui:replace `touse'=0 if `touse'==1 & `tvar2'>=`gvar' & `gvar'!=0 & `tvar'>=`gvar'

	** If no never treated
	qui:count if `gvar'==0 & `touse'==1
	local nnever=0
	local gvarmax= .
	if `r(N)'==0 {
		qui:sum `gvar' if `touse'==1 , meanonly
		local gvarmax = r(max)
		qui:replace `touse'=0 if `touse'==1 & `tvar'>=`gvarmax'
		local nnever=1
	}

	*** Define the gap (across gvar tvar)
	mata: st_view(xs1 =.,.,"`gvar'","`touse'")
	mata: st_view(xs2 =.,.,"`tvar'","`touse'")
	mata: xs = uniqrows((xs1\xs2))
	mata: xs=select(xs,(xs:>0))
	mata: gap=min((xs[2..rows(xs),1]:-xs[1..rows(xs)-1,1]))
	mata: st_local("gap",strofreal(gap))
	mata: mata drop xs gap xs1 xs2

	local antigap = `gap'*`anti'
	local antigap0 = `gap'*(`anti'-1)


	** Redefine Always treated
	tempvar tvar2
	qui:bysort `touse' `ivar': egen long `tvar2'=min(`tvar')
	qui:replace `touse'=0 if `touse'==1 & `tvar2'>=(`gvar'-`antigap0') & `gvar'!=0 & `tvar'>=(`gvar'-`antigap0')


	** Never makes estimation like SUN ABRaham
	** or CSDID with REG
	if "`trtvar'"=="" {
		qui:capture drop __tr__
		qui:gen byte __tr__=0 if `touse'
		//display in w "`gvarmax'"
		qui:replace  __tr__=1 if `tvar'>=(`gvar'-`antigap') & `gvar'>0  & `touse'
		qui:replace  __tr__=1 if `touse' & "`never'"!=""
		qui:replace  __tr__=0 if `touse' & `gvar'>=`gvarmax'

	}
	else {
		error 1
		qui:capture drop __tr__
		qui:gen      __tr__=`trtvar' if `touse'
		qui:replace  __tr__=1        if `touse' & "`never'"!="" & `trtvar'==0 & `gvar'!=0
		qui:replace  __tr__=0        if `touse' & `gvar'>=`gvarmax'
		qui:replace  __tr__=0 if `touse' & `tvar'<(`gvar'-`antigap')
	}

	** But effect is done for effectively treated so
	qui:capture drop __etr__
	qui:gen byte __etr__=0 if `touse'
	qui:replace  __etr__=1 if `touse' & `tvar'>(`gvar'-`antigap') & `gvar'>0

	qui:levels `gvar' if `touse' & `gvar'>0 & `gvar'<`gvarmax', local(glist)
	sum `tvar' if `touse' , meanonly
	qui:levels `tvar' if `touse' & `tvar'>=r(min), local(tlist)

	*** Center Covariates
	if "`weight'"!="" local wgt aw

** Define Toabs based on Het Type
************************************
	tempvar toabshere
	if "`ehettype'"=="timecohort"  qui:egen `toabshere'=group(`gvar' `tvar') if `touse'
	if "`ehettype'"=="cohort"      {
		qui: capture drop __post__
		qui: gen byte __post__ = 0 if `touse'
		qui: replace  __post__ = 1 if `tvar'< (`gvar'-`antigap' ) & `gvar'>0 &  `touse'
		qui: replace  __post__ = 2 if `tvar'>=(`gvar'-`antigap0') & `gvar'>0 &  `touse'
		qui: label define __post__ 0 "Base" 1 "Pre-Trt" 2 "Post-Trt", modify
		qui: label values __post__ __post__
		qui:egen `toabshere'=group(`gvar' __post__) if `touse'
	}
	if "`ehettype'"=="time"        {
		qui: capture drop __post__
		qui: gen byte __post__ = 0 if `touse'
		qui: replace  __post__ = 1 if `tvar'< (`gvar'-`antigap' ) & `gvar'>0 &  `touse'
		qui: replace  __post__ = 2 if `tvar'>=(`gvar'-`antigap0') & `gvar'>0 &  `touse'
		qui: label define __post__ 0 "Base" 1 "Pre-Trt" 2 "Post-Trt", modify
		qui: label values __post__ __post__
		qui:egen `toabshere'=group(`tvar' __post__ ) if `touse'
	}
	if "`ehettype'"=="twfe"        {
		qui: capture drop __post__
		qui: gen byte __post__ = 0 if `touse'
		qui: replace  __post__ = 1 if `tvar'< (`gvar'-`antigap' ) & `gvar'>0 &  `touse'
		qui: replace  __post__ = 2 if `tvar'>=(`gvar'-`antigap0') & `gvar'>0 &  `touse'
		qui: label define __post__ 0 "Base" 1 "Pre-Trt" 2 "Post-Trt", modify
		qui: label values __post__ __post__
		qui:egen `toabshere'=group( __post__ ) if `touse'
	}
	if "`ehettype'"=="event"        {

		qui: capture drop __evnt__
		qui: gen byte __evnt__ = (`tvar'-`gvar')*(`gvar'>0) -`gap'*(`gvar'==0) if `touse'
        if "`rul'"!="" qui: replace __evnt__=`rul' if __evnt__>`rul' & __evnt__!=.
        if "never"!="" & "`rll'"!="" qui: replace __evnt__=`rll' if __evnt__<`rll' & __evnt__!=.
        qui: sum __evnt__ if `touse', meanonly
        local cev = 1-`r(min)'
        qui: replace __evnt__ = __evnt__+(`cev')
		qui:egen `toabshere'=group( __evnt__ ) if `touse'

	}
    if "`ehettype'"=="eventcohort"  {
        local never never
    	qui: capture drop __evnt__
		qui: gen byte __evnt__ = (`tvar'-`gvar')*(`gvar'>0) -`gap'*(`gvar'==0) if `touse'
        ** Recodes
        parse_hettype_evco `hettype'
        local evbase = r(evbase)
        **base(numlist max=1) erecode(stringasis)
        sum __evnt__, meanonly
        if `r(min)'<0 {
            display as error "All values after Recode should be strictly possitive"
            error 1
        }

        qui:egen `toabshere'=group(`gvar' __evnt__ ) if `touse'
    }
************************************
** Two options: Either we Demean  data, or used actual data
** Same Results
	if "`xasis'"=="" {
		if "`x'"!="" {
				capture drop _x_*
				qui:hdfe `y' `x' if `touse'	[`wgt'`exp'], abs(`toabshere') 	keepsingletons  gen(_x_)
				capture drop _x_`y'
				local xxvar _x_*
		}
	}
	else local xxvar `x'

	*****************************************************
	*****************************************************
	// If Hettype Full
	if "`ehettype'"=="timecohort" {
**********************************************************************************************************
		foreach i of local glist {
			foreach j of local tlist {
				qui:count if `i'==`gvar' & `j'==`tvar' & `touse'
				if `r(N)'>0 {
					if "`never'"!="" {
						if (`i'-`antigap')!=`j' {

						local xvar  `xvar'   c.__tr__#i`i'.`gvar'#i`j'.`tvar'
						local xvar2 `xvar2'           i`i'.`gvar'#i`j'.`tvar'

						if "`x'"!="" {
							local xvar  `xvar'   c.__tr__#i`i'.`gvar'#i`j'.`tvar'#c.(`xxvar')
							local xvar3 `xvar3'           i`i'.`gvar'#i`j'.`tvar'#c.(`xxvar')
							}
						}
					}
					else if `j'>=(`i'-`antigap0') {

						local xvar `xvar'   c.__tr__#i`i'.`gvar'#i`j'.`tvar'
						local xvar2 `xvar2'          i`i'.`gvar'#i`j'.`tvar'

						if "`x'"!="" {
							local xvar  `xvar'  c.__tr__#i`i'.`gvar'#i`j'.`tvar'#c.(`xxvar')
							local xvar3 `xvar3'          i`i'.`gvar'#i`j'.`tvar'#c.(`xxvar')
						}

					}
				}
			}
		}
**********************************************************************************************************
	}
	else if "`ehettype'"=="time" {
**********************************************************************************************************
		foreach i in 1 2 {
			foreach j of local tlist {
				qui:count if `i'==__post__ & `j'==`tvar' & `touse'
				if `r(N)'>0 {
					if "`never'"!="" {

						local xvar `xvar'   c.__tr__#i`i'.__post__#i`j'.`tvar'
						local xvar2 `xvar2'          i`i'.__post__#i`j'.`tvar'

						if "`x'"!="" {
							local xvar `xvar'   c.__tr__#i`i'.__post__#i`j'.`tvar'#c.(`xxvar')
							local xvar3 `xvar3'          i`i'.__post__#i`j'.`tvar'#c.(`xxvar')
						}

					}
					else if `i'==2 {

						local xvar `xvar'   c.__tr__#i`i'.__post__#i`j'.`tvar'
						local xvar2 `xvar2'          i`i'.__post__#i`j'.`tvar'

						if "`x'"!="" {
							local xvar  `xvar'  c.__tr__#i`i'.__post__#i`j'.`tvar'#c.(`xxvar')
							local xvar3 `xvar3'          i`i'.__post__#i`j'.`tvar'#c.(`xxvar')
						}

					}
				}
			}
		}

**********************************************************************************************************
	}
	else if "`ehettype'"=="cohort" {
**********************************************************************************************************
		foreach i of local glist {
			foreach j in 1 2 {
				qui:count if `i'==`gvar' & `j'==__post__ & `touse'
				if `r(N)'>0 {
					if "`never'"!="" {

						local xvar `xvar'   c.__tr__#i`i'.`gvar'#i`j'.__post__
						local xvar2 `xvar2'          i`i'.`gvar'#i`j'.__post__

						if "`x'"!="" {
							local xvar `xvar'   c.__tr__#i`i'.`gvar'#i`j'.__post__#c.(`xxvar')
							local xvar3 `xvar3'          i`i'.`gvar'#i`j'.__post__#c.(`xxvar')
						}

					}
					else if `j'==2 {

						local xvar `xvar'   c.__tr__#i`i'.`gvar'#i`j'.__post__
						local xvar2 `xvar2'          i`i'.`gvar'#i`j'.__post__

						if "`x'"!="" {
							local xvar  `xvar'  c.__tr__#i`i'.`gvar'#i`j'.__post__#c.(`xxvar')
							local xvar3 `xvar3'          i`i'.`gvar'#i`j'.__post__#c.(`xxvar')
						}

					}
				}
			}
		}

**********************************************************************************************************
	}
	else if "`ehettype'"=="event" {
**********************************************************************************************************
    local gpevent = -`antigap'
    qui:levelsof __evnt__ if `touse', local(elist)
    if "`never'"=="" qui:levelsof __evnt__ if `touse' & __evnt__>-`gap', local(elist)

	** Create __event__ and label it
	** use __evnt__ to avoid conflict with other variables
	foreach i of local elist {
		local ccev = `i'-`cev'
		  if (`ccev')< 0  label define __evnt__ `i' "t`ccev'" , modify
		else if (`i'+`cev')> 0  label define __evnt__ `i' "t+`ccev'", modify
		else if (`i'+`cev')==0  label define __evnt__ `i' "t+0"     , modify
	}
	label values __evnt__ __evnt__
	foreach i of local elist {
		local ccev = `i'-`cev'
		qui:count if `i'==__evnt__ & `touse'
			if `r(N)'>0 {
				if "`never'"=="" & (`ccev'>-`antigap') {
					local xvar `xvar'   c.__tr__#i`i'.__evnt__
					local xvar2 `xvar2'          i`i'.__evnt__
					if "`x'"!="" {
						local xvar `xvar'   c.__tr__#i`i'.__evnt__#c.(`xxvar')
						local xvar3 `xvar3'          i`i'.__evnt__#c.(`xxvar')
					}
				}
				if "`never'"!="" & `ccev'!=(-`antigap') {
					local xvar `xvar'   c.__tr__#i`i'.__evnt__
					local xvar2 `xvar2'          i`i'.__evnt__
					if "`x'"!="" {
						local xvar `xvar'   c.__tr__#i`i'.__evnt__#c.(`xxvar')
						local xvar3 `xvar3'          i`i'.__evnt__#c.(`xxvar')
					}
				}
			}
		}

**********************************************************************************************************
	}
    else if "`ehettype'"=="eventcohort" {
**********************************************************************************************************
	qui:levelsof __evnt__, local(elist)
    	foreach i of local glist {
			foreach j of local elist {
				qui:count if `i'==`gvar' & `j'==__evnt__ & `touse'
				if `r(N)'>0 {
					if `j'!=`evbase' {
						local xvar `xvar'   c.__tr__#i`i'.`gvar'#i`j'.__evnt__
						local xvar2 `xvar2'          i`i'.`gvar'#i`j'.__evnt__

						if "`x'"!="" {
							local xvar `xvar'   c.__tr__#i`i'.`gvar'#i`j'.__evnt__#c.(`xxvar')
							local xvar3 `xvar3'          i`i'.`gvar'#i`j'.__evnt__#c.(`xxvar')
							}
					}

				}
			}
		}

**********************************************************************************************************
	}
	else if "`ehettype'"=="twfe" {
		** TWFE, Thus imposing no heterogeneity. One can still estimate Event effects based on covariate heterogeneity
		foreach i in 1 2 {
				if "`never'"!="" {

					local xvar `xvar'   c.__tr__#i`i'.__post__
					local xvar2 `xvar2'          i`i'.__post__

					if "`x'"!="" {
						local xvar `xvar'   c.__tr__#i`i'.__post__#c.(`xxvar')
						local xvar3 `xvar3'          i`i'.__post__#c.(`xxvar')
					}

				}
				else if `i'==2 {

					local xvar `xvar'   c.__tr__#i`i'.__post__
					local xvar2 `xvar2'          i`i'.__post__

					if "`x'"!="" {
						local xvar  `xvar'  c.__tr__#i`i'.__post__#c.(`xxvar')
						local xvar3 `xvar3'          i`i'.__post__#c.(`xxvar')
					}

				}
		}
	}
	** for xs: Interaction with Glist and Tlist

	foreach i of local glist {
		          local ogxvar `ogxvar' i`i'.`gvar'#c.(`xvarvar' `xgvar')
	}

	foreach j of local tlist {
		* To avoid Multicolinearity in Simple cases
        local cj = `cj'+1
        if `cj'>1 local otxvar `otxvar' i`j'.`tvar'#c.(`x' `xtvar')
	}


 	*display in w "t:`otxvar'"
	*display in w "g:`xvar'"
	** Cluster level
	if "`cluster'"=="" & "`ivar'"=="" local cvar
	if "`cluster'"=="" & "`ivar'"!="" local cvar `ivar'
	if "`cluster'"!=""                local cvar `cluster'

	if "`method1'"=="fracreg" local tocluster vce(cluster `cvar')
	else local tocluster cluster(`cvar')

	if "`method'"=="" {
		if "`group'"=="" {
			** ogxvar  will be excluded if they are fixed across time
			if "`tocluster'"=="" local tocluster vce(robust)
			reghdfe `y' `xvar' `ogxvar'  `otxvar' 	`exogvar' ///
				if `touse' [`weight'`exp'], abs(`ivar' `tvar' `fevar') `tocluster' keepsingletons `options'
			local scmd `e(cmdline)'
		}
		else {
			if "`ivar'"!="" {
				qui:xtset `ivar' `tvar'
				mata:is_balanced("`ivar' `tvar'","`touse'")

				if "`corr'"!="" {
					** Correction
					qui:myhdmean `xvar' `x' `ogxvar'  `otxvar' `exogvar'  i.`tvar' if `touse'	[`wgt'`exp'] , prefix(_z_) keepsingletons abs(`ivar')
					local xcorr  `r(vlist)'
				}
			}
			reghdfe `y' `xvar'  `x'  `ogxvar' `otxvar'   `exogvar' `xcorr' ///
			if `touse' [`weight'`exp'], abs(`gvar'  `tvar' `fevar') `tocluster' keepsingletons noempty `options'
			local scmd `e(cmdline)'
		}
	}
	else if "`method'"=="ppmlhdfe" {

		ppmlhdfe `y' `xvar' `ogxvar'  `otxvar'	`exogvar' ///
				if `touse' [`weight'`exp'], abs(`ivar' `tvar' `fevar') `tocluster' keepsingletons ///
				d `method_option' `options'
		local scmd `e(cmdline)'
	}
	else {
		if "`ivar'"!="" {
			qui:xtset `ivar' `tvar'
			mata:is_balanced("`ivar' `tvar'","`touse'")
			if   "`corr'"!=""  {
					** Correction
					qui:myhdmean `xvar'  `x'  `ogxvar' `otxvar' `xcorr' `exogvar'  i.`tvar' if `touse'	[`wgt'`exp'] , prefix(_z_) keepsingletons abs(`ivar')
					local xcorr  `r(vlist)'
			}
		}
		`method'  `y' `xvar'  `x'  `ogxvar' `otxvar' `xcorr' `exogvar'   i.`gvar' i.`tvar' ///
		if `touse' [`weight'`exp'], `tocluster' `method_option' `options'
		local scmd `e(cmdline)'
	}

	ereturn local cmd jwdid
	ereturn local cmd2 `method'
	ereturn local cmdopt `method_option'

	ereturn local cmdline jwdid `0'
	ereturn local scmd `scmd'
	ereturn local hettype `ehettype'
	ereturn local estat_cmd jwdid_estat
	if "`never'"!="" ereturn local type  never
	else 			 ereturn local type  notyet

	ereturn local ivar `ivar'
	ereturn local tvar `tvar'
	ereturn local gvar `gvar'

	ereturn scalar  gap =  `gap'
	ereturn scalar  anticipation =  `anti'
	ereturn scalar  antigap =  `antigap'

end

mata
void is_balanced(string scalar ivars, string scalar touse){
	real matrix ivar, tvar, inf, ord

	ivar=st_data(.,ivars,touse)
	ord=order(ivar,(1,2))
	inf=panelsetup(ivar,1)
	// same number of observations
	real scalar max1, min1, max2 , max3, min2 , min3
	max1=max(inf[,2]:-inf[,1])
	min1=min(inf[,2]:-inf[,1])
	// same max and min
	max2=max(ivar[inf[,1],2])
	min2=min(ivar[inf[,1],2])
	max3=max(ivar[inf[,2],2])
	min3=min(ivar[inf[,2],2])
	if ( (max1==min1) & (max2==min2) & (max3==min3)) st_local("ibal","1")
	else st_local("ibal","0")
}
end

program myhdmean, rclass
	syntax anything [if] [aw iw pw fw], abs(varlist) prefix(name) [compact  keepsingletons]

	ms_fvstrip `anything' `if', expand dropomit
	local vvlist `r(varlist)'
	** First check and create
	** local k =0 for names
	foreach i in `vvlist' {
		local k=`k'+1
		capture confirm variable `i'
		if _rc!=0 {
			if length(strtoname("`i'"))<25 local vn = strtoname("`i'")
			else local vn _nvar_`k'
			gen double `vn'=`i'
			label var `vn' `"`i'"'
			local dropvlist `dropvlist' `vn'

		}
		else local vn `i'

		local vflist `vflist' `vn'
	}

	if "`compact'"=="" {
		foreach i in `vflist' {
			local cnt
			local fex
			foreach j of varlist `abs' {
				local cnt=`cnt'+1
				capture drop `prefix'`cnt'_`i'
				local fex `fex' `prefix'`cnt'_`i'=`j'
				local vlist `vlist' `prefix'`cnt'_`i'
			}
			qui:reghdfe `i' `if'  [`weight'`exp'], abs(`fex')  `keepsingletons'
			local vlab:variable label `i'

			label var `prefix'`cnt'_`i' "`vlab'"
		}
		local vflist `vlist'
		local vlist
		foreach i in `vflist' {
			capture:{
				sum `i', meanonly
				if abs(`r(max)'-`r(min)')>epsfloat() local vlist `vlist' `i'
				else local dropvlist `dropvlist' `i'
			}
		}

		return local vlist  `vlist'
	}
	else {
		foreach i in  `vflist' {
			local cnt
			local fex
			capture drop `prefix'`cnt'_`i'
			qui:reghdfe `i' `if'  [`weight'`exp'], abs(`abs') resid `keepsingletons'
			qui:gen double `prefix'`cnt'_`i'=`i'-_reghdfe_resid-_cons
			local vlist `vlist' `prefix'`cnt'_`i'
			qui:drop _reghdfe_resid

		}

		local vflist `vlist'
		local vlist
		foreach i in `vflist' {
			sum `i', meanonly
			if abs(`r(max)'-`r(min)')>epsfloat() local vlist `vlist' `i'
			else local dropvlist `dropvlist' `i'
		}
		return local vlist   `vlist'
	}
	*display in w "`dropvlist'"
	if "`dropvlist'"!="" drop `dropvlist'

end

** Aux var for jwdid
program _gjwgvar, sortpreserve
	syntax newvarname =/exp [if] [in], tvar(varname) ivar(varname)
	local exp = subinstr("`exp'","(","",.)
	local exp = subinstr("`exp'",")","",.)
	tempvar touse
	qui:gen byte `touse'=0
	qui:replace `touse'=1 `if' `in'
	qui:replace `touse'=0 if `tvar'==. | `ivar'==. | `exp'==.
	tempvar vals
	sum `exp' if `touse' , meanonly
	local lmin=r(min)
	local lmax=r(max)
	if `lmin'<0 | `lmax'>1 {
			display in r "`exp' can only have values between 0 and 1"
			error 4444
	}
	qui: {
		tempvar aux auxd
		qui: gen byte `auxd'=`exp'>0 if `exp'!=.
		bysort `touse' `ivar' `auxd':egen `aux'=min(`tvar')
		replace `aux'=0 if `exp'==0
		by     `touse' `ivar':egen `varlist'=max(`aux')
		replace `varlist'=. if `exp'==. | !`touse'
	}
	label var `varlist' "Group Variable based on `exp'"
end

*** Problem.
/*
What to do if DIF(1) c.x does give you a different result from dif() c.dx
So far Cohort works well, because DIFF is based on cohort
We need to figure something similar for the others. Perhaps it would work
if DIFF depends on the Constrained variable
*/