*! v2.0 FRA. Gravity
* v1.72 FRA. Anticipation without Never
* v1.71 FRA. Bug with Pretrend
* v1.7 FRA. Fixes how to Store Table (with new names)
* v1.6 FRA. Fixes to esave, and Orestriction
* v1.51 FRA. adds Window to event
* v1.5 FRA. Fix Bug with Continuous treatment
*           adds PTA test
* v1.42 FRA. flexible PLOT
* v1.41 FRA. Changes | fpr &
* v1.4 FRA. Allows for treatment to be continuous. With ASIS
* v1.37 FRA. Adds Over for Simple aggregations: Will allow for other aggregations at will
* v1.35 FRA. adds method to mlogit
* v1.34 FRA. Small changes on Other
* v1.33 FRA. Changes output (not AT anymore)
* Also allows for "other" as condition
* v1.32 FRA. Prepares for did_plot
* v1.31 FRA. Prepares for jwdid_plot
* v1.3 FRA. Corrects Never
* v1.2 FRA. some beutification
* v1.1 FRA. Adds margins event with labels
* v1 8/5/2022 FRA. Adds margins the right way

program define addr, rclass
		return add
        return `0'
end

program define adde, eclass
		ereturn `0'
end

program define jwdid_estat, sortpreserve
	version 14
    syntax anything [pw], [* ]
        if "`e(cmd)'" != "jwdid" {
                error 301
        }

		if "`e(cmd2)'"!="" adde local cmd  `e(cmd2)'
        gettoken key rest : 0, parse(", ")

		tempname last
		qui:est sto `last'
		capture noisily {
			if inlist("`key'","simple","group","calendar","event","plot") {
				jwdid_`key'  `rest'
				addr local cmd  estat
				addr local cmd2 jwdid
				/*if "`key'"=="plot"  {
					jwdid_plot, `plot1'
				} */

			}
			else {
				display in red "Option `key' not recognized"
					error 199
			}
		}
		if _rc!=0 {
			qui:est restore `last'
		}
		adde local cmd jwdid
end
**capture program drop jwdid_window
program jwdid_window, rclass
    syntax , [window(numlist min=2 max=2) cwindow(numlist min=2 max=2)]
    numlist "`window'`cwindow'", min(2) max(2) sort integer
    local window `r(numlist)'
    local n1: word 1 of `window'
    local n2: word 2 of `window'
    numlist "`n1'/`n2'", int
    return local window `r(numlist)'
	return local rmin   `n1'
	return local rmax   `n2'
end

program orest
	syntax , selvar(name) [orestriction(string asis)]
	if `"`orestriction'"' == "" {
		gen byte `selvar'=1
	}
	else {
		gen byte `selvar'=0
		qui:replace  `selvar'=1 if `orestriction'
	}
end

program define jwdid_simple, rclass
		syntax [pw], [* post estore(str) esave(str asis) replace over(varname) ///
                    asis  OREStriction(passthru) ///
                    window(numlist min=2 max=2)]
		//tempvar aux
		//qui:bysort `e(ivar)':egen `aux'=min(`e(tvar)') if e(sample)
		capture:est store `lastreg'
		tempname lastreg
		capture:qui:est store `lastreg'
		tempvar etr

		** Arbitrary Restriction
		tempvar tosel
		orest, `orestriction' selvar(`tosel')

		if "`over'"!="" qui: gen `etr'=`over' if !inlist(`over',0,.) & __etr__==1

		else local etr
		if "`asis'"=="" {
			qui:margins [`weight'`exp'],  subpop(if __etr__==1 & `tosel') at(__tr__=(0 1)) ///
					noestimcheck contrast(atcontrast(r)) ///
					`options' post over(`etr')
		}
		else {
			qui:margins [`weight'`exp'],  subpop(if __etr__==1 & `tosel') at(__tr__=0) at((asobserved) __tr__) ///
					noestimcheck contrast(atcontrast(r)) ///
					`options' post over(`etr')
		}
		tempname table b V
		matrix `table' = r(table)
		matrix `b' = e(b)
		matrix `V' = e(V)

		local nm:colnames `b'
		local nm = subinstr("`nm'","r2vs1._at@","",.)

		if `"`over'"'!="" qui:levelsof `etr'  , local(ol)

		if `:word count `ol''>1 {
			foreach i of local ol {
				local snm `snm' simple`i'
			}
		}
		else local snm simple

		matrix colname `b' = `snm'
		matrix colname `V' = `snm'
		matrix rowname `V' = `snm'
		tempname bb VV
		matrix `bb' = `b'
		matrix `VV' = `V'
		adde repost b=`bb' V=`VV', rename

		ereturn display
		tempname tb2
		matrix `tb2' = r(table)

		if "`estore'"!="" est store `estore'
		if `"`esave'"'!="" est save `esave', `replace'
		if "`post'"=="" qui:est restore `lastreg'

		return matrix table = `tb2'
		return matrix b = `b'
		return matrix V = `V'
		return local ecmd jwdid_estat
		return local agg simple
end

program define jwdid_group, rclass
		syntax [pw], [* post estore(str) esave(str asis) replace  OREStriction(passthru) asis ]
		tempvar aux
		qui:bysort `e(gvar)' `e(ivar)':egen `aux'=min(`e(tvar)') if e(sample)

		capture:est store `lastreg'
		tempname lastreg
		capture:qui:est store `lastreg'

		** Arbitrary Restriction
		tempvar tosel
		orest, `orestriction' selvar(`tosel')

		capture drop __group__
		qui:clonevar __group__ =  `e(gvar)' if __etr__==1 & `aux'<`e(gvar)'

		if "`asis'"=="" {
			qui:margins [`weight'`exp'], subpop(if __etr__==1 & `tosel' ) at(__tr__=(0 1)) ///
				  over(__group__) noestimcheck contrast(atcontrast(r)) ///
				  `options'  post
		}
		else {
			qui:margins [`weight'`exp'],  subpop(if __etr__==1 & `tosel') at(__tr__=0) at((asobserved) __tr__) ///
					over(__group__) noestimcheck contrast(atcontrast(r)) ///
				  `options'  post
		}


		tempname table b V
		matrix `table' = r(table)
		matrix `b' = e(b)
		matrix `V' = e(V)

		local nm:colnames `b'
		local nm = subinstr("`nm'","r2vs1._at@","",.)

		matrix colname `b' = `nm'
		matrix colname `V' = `nm'
		matrix rowname `V' = `nm'
		tempname bb VV
		matrix `bb' = `b'
		matrix `VV' = `V'
		adde repost b=`bb' V=`VV', rename

		ereturn display
		tempname tb2
		matrix `tb2' = r(table)

		if "`estore'"!="" est store `estore'
		if `"`esave'"'!="" est save `esave', `replace'
		if "`post'"=="" qui:est restore `lastreg'

		return matrix table = `tb2'
		return matrix b = `b'
		return matrix V = `V'
		return local agg group
		return local ecmd jwdid_estat
		capture drop __group__
end

program define jwdid_calendar, rclass
	syntax [pw], [* post estore(str) esave(str asis) replace  OREStriction(passthru)  ]
		capture drop __calendar__
		tempvar aux
		qui:bysort `e(gvar)' `e(ivar)':egen `aux'=min(`e(tvar)') if e(sample)
		qui:clonevar __calendar__ =  `e(tvar)' if __etr__==1 & `aux'<`e(gvar)'

		capture:est store `lastreg'
		tempname lastreg
		capture:qui:est store `lastreg'

		** Arbitrary Restriction
		tempvar tosel
		orest, `orestriction' selvar(`tosel')


		if "`asis'"=="" {
			qui:margins [`weight'`exp'], subpop(if __etr__==1 & `tosel') at(__tr__=(0 1)) ///
				  over(__calendar__) noestimcheck contrast(atcontrast(r)) ///
				  `options'  post
		}
		else {
			qui:margins [`weight'`exp'],  subpop(if __etr__==1 & `tosel') at(__tr__=0) at((asobserved) __tr__) ///
					over(__calendar__) noestimcheck contrast(atcontrast(r)) ///
				  `options'  post
		}

		tempname table b V
		matrix `table' = r(table)
		matrix `b' = e(b)
		matrix `V' = e(V)

		local nm:colnames `b'
		local nm = subinstr("`nm'","r2vs1._at@","",.)

		matrix colname `b' = `nm'
		matrix colname `V' = `nm'
		matrix rowname `V' = `nm'
		tempname bb VV
		matrix `bb' = `b'
		matrix `VV' = `V'
		adde repost b=`bb' V=`VV', rename

		ereturn display
		tempname tb2
		matrix `tb2' = r(table)


		if "`estore'"!="" est store `estore'
		if `"`esave'"'!="" est save `esave', `replace'
		if "`post'"=="" qui:est restore `lastreg'

		return matrix table = `tb2'
		return matrix b = `b'
		return matrix V = `V'
		return local agg calendar
		return local ecmd jwdid_estat
		capture drop __calendar__
end

program define jwdid_event, rclass
	syntax [pw], [post estore(str) esave(str asis) replace  OREStriction(passthru)   asis * pretrend ///
                    window(passthru) cwindow(passthru)]
		capture drop __event__
		tempvar aux
		qui:bysort `e(gvar)' `e(ivar)':egen `aux'=min(`e(tvar)') if e(sample)
		qui:sum `e(tvar)' if e(sample), meanonly
		qui:gen __event__ = `e(tvar)'-`e(gvar)' if `e(gvar)'!=0 & e(sample)

        ** If window
        tempvar sel
        gen byte `sel'=1
		if (("`window'"!="")+("`cwindow'"!=""))>1 {
			display as error "Only window() or cwindow() allowed"
			error 1
		}

        if "`window'`cwindow'"!="" {
            jwdid_window, `window' `cwindow'
            local lwind `r(window)'
			local lwmin `r(rmin)'
			local lwmax `r(rmax)'
			if "`window'"!="" {
                qui:replace  `sel'=0
				foreach i of local lwind {
					qui:replace `sel'=1 if __event__==`i'
				}
			}
			else if "`cwindow'"!="" {
				qui:replace  __event__=`lwmin' if __event__<`lwmin' & __event__!=.
				qui:replace  __event__=`lwmax' if __event__>`lwmax' & __event__!=.
			}
		}


		capture:est store `lastreg'
		tempname lastreg
		capture:qui:est store `lastreg'

		** Arbitrary Restriction
		tempvar tosel
		orest, `orestriction' selvar(`tosel')

		*qui:replace __event__ =__event__ - 1 if  __event__ <0
		if "`e(type)'"=="notyet" {
****
            local nvr = "on"
			capture drop __event2__
			qui:sum __event__ , meanonly
			local rmin = r(min)
			qui:replace __event__=1+__event__-r(min)
			qui:levelsof __event__, local(lv)
			foreach i of local lv {
				label define __event__ `i' "`=-1+`i'+`rmin''", modify
			}
			label values __event__ __event__

****
				if "`asis'"=="" {
					qui:margins [`weight'`exp'], subpop(if `sel' & __etr__==1 & `tosel') at(__tr__=(0 1)) ///
						  over(__event__) noestimcheck contrast(atcontrast(r)) ///
						  `options'  post
				}
				else {
					qui:margins [`weight'`exp'],  subpop(if `sel' & __etr__==1 & `tosel') at(__tr__=0) at((asobserved) __tr__) ///
							over(__event__) noestimcheck contrast(atcontrast(r)) ///
						  `options'  post
				}
		}
		else if "`e(type)'"=="never" {
            local nvr = "on"
			capture drop __event2__
			qui:sum __event__ , meanonly
			local rmin = r(min)
			qui:replace __event__=1+__event__-r(min)
			qui:levelsof __event__, local(lv)
			foreach i of local lv {
				label define __event__ `i' "`=-1+`i'+`rmin''", modify
			}
			label values __event__ __event__

			if "`asis'"=="" {
				qui:margins [`weight'`exp'], subpop(if `sel' & __tr__!=0 & `tosel') at(__tr__=(0 1)) ///
					  over(__event__) noestimcheck contrast(atcontrast(r)) ///
					  `options'  post
			}
			else {
				qui:margins [`weight'`exp'],  subpop(if `sel' & __tr__!=0 & `tosel') at(__tr__=0) at((asobserved) __tr__) ///
						over(__event__) noestimcheck contrast(atcontrast(r)) ///
					  `options'  post
			}

		}


		tempname table b V
		matrix `table' = r(table)
		matrix `b' = e(b)
		matrix `V' = e(V)

				local nm:colnames `b'
		local nm = subinstr("`nm'","r2vs1._at@","",.)

		matrix colname `b' = `nm'
		matrix colname `V' = `nm'
		matrix rowname `V' = `nm'
		tempname bb VV
		matrix `bb' = `b'
		matrix `VV' = `V'
		adde repost b=`bb' V=`VV', rename

		ereturn display
		tempname tb2
		matrix `tb2' = r(table)
        *** PTA

        if "`pretrend'"!="" & "`nvr'"=="on" {
            qui:levelsof __event__ if `sel' , local(lv)
			foreach i of local lv {
				if `=-1+`i'+`rmin''<-1 local totest `totest' `i'.__event__
			}
			display in result "Pre-treatment test"
            test `totest'
			scalar pre_chi2= r(chi2)
			scalar pre_dfr = r(df_r)
			scalar pre_p   = r(p)
        }

		if "`estore'"!="" est store `estore'
		if `"`esave'"'!="" est save `esave', `replace'
		if "`post'"=="" qui:est restore `lastreg'

		return matrix table = `tb2'
		return matrix b = `b'
		return matrix V = `V'
		return local agg event
		return local ecmd jwdid_estat
		if "`pretrend'"!="" {
			return scalar pre_chi2= pre_chi2
			return scalar pre_df = pre_dfr
			return scalar pre_p  = pre_p
		}
		*capture drop __event__
end