* Need to create submodules!
* Like joyplot but for lines. Together lines. area lines.? Stack area?
* stream
*capture program drop ridge_line
*capture program drop _rangevar
*program drop _all
program _rangevar, sortpreserve rclass
	syntax varlist, [radj(real 0.0) nobs(real 0.0) rvar(string) offset(real 0.0) range(numlist)]

		if "`rangeasis'"=="" {
			** S1: Readjust range
			sum `varlist', meanonly
			local vmin  = r(min)-(r(max)-r(min))*`radj'
			local vmin2 = r(min)-(r(max)-r(min))*(`radj')+`offset'
			local vmax2 = r(max)+(r(max)-r(min))*(`radj')+`offset'
			*display in w "`vmin':`vmin2'"
			local vmax = r(max)+(r(max)-r(min))*`radj'
			** Verify range
			if  "`range'"!="" {
				numlist "`range'", sort
				local range `r(numlist)'

				local rmin:word 1 of `range'
				local rmax:word 2 of `range'
				local vmin=`rmin'
				local vmax=`rmax'
				local vmin2=`rmin'+`offset'
				local vmax2=`rmax'+`offset'
			}
			** S2: Create the Range So Kdensities can be ploted
			range `rvar' `vmin' `vmax' `nobs'
			if "`:var label `varlist''"!="" label var `rvar' "`:var label `varlist''"
			else label var `rvar' `varlist'
			format `:format `varlist'' `rvar'
		}


	return local vmin =`vmin'
	return local vmin2=`vmin2'
	return local vmax =`vmax'
	return local vmax2 =`vmax2'
end

program _over, rclass
	syntax [anything], gen(string)

	if "`anything'"=="" {
		qui:gen byte `gen'=1
	}
	else {
		capture confirm numeric var `anything'
		if _rc!=0 {
				*tempvar nb
				encode `anything', gen(`gen')

		}
		else {
			clonevar `gen'=`anything'
		}
	}
end

program ridgeline_plot
	syntax varlist(min=2 max=2) [if] [in] [iw/], over(varname) [ ///
	radj(real 0)   /// Range Adjustment. How much to add or substract to the top bottom.
	range(numlist min=2 max=2) ///
	offset(real 0) /// to move text
	dadj(real 1)   /// Adjustment to height. Baseline. 1/grps
	badj(real 0)   /// Adjustment to base. Default 0
	bwadj(numlist >=0 <=1)  /// Adj on BW 0 uses average, 1 uses individual bw's
	bwadj2(real 0.2)  /// Adj on BW 0.1
	bwadj3(numlist >0 )  /// bw for all
	kernel(string)  ///
	degree(int 0)   ///
	nobs(int 200)   ///
	color(string asis)   /// only colorlist
	colorpalette(string asis) /// Uses Benjann's Colors with all the options.
	strict notext right  textopt(string) ///
	gap0 alegend ///
    fcolor(passthru)        ///  fill color and opacity
    fintensity(passthru) 	///  fill intensity
    lcolor(passthru)        ///  outline color and opacity
    lwidth(passthru)     	///  thickness of outline
    lpattern(passthru) 		///  outline pattern (solid, dashed, etc.)
    lalign(passthru) 		///   outline alignment (inside, outside, center)
    lstyle(passthru) 		///
    stack stack100 ///
	STREAM  STREAM1(numlist max=1 >0)  half   ///  Stack, Stack graph, Stream(to move things)
	NORMalize sum asis	/// asis. use data as given; sum to get sums of data; norm
	addplot(string asis) * default]     //  overall look of outline

    version 16

	*** Get sample
	marksample touse
	markout `touse' `varlist' `over' `exp', strok
	** Basic way of doing this. Triangular
	if "`kernel'"=="" local kernel tri
	if "`bwadj'"=="" local bwadj=0
	if "`stream'`stream1'"!="" & "`stack'`stack100'"=="" local stack stack


	tempname frame
	frame put `varlist' `over' `exp'  if `touse', into(`frame')

	qui:frame `frame': {

		** make variable numeric with labels
		tempvar nb
 		_over `over', gen(`nb')
		local over `nb'

		**Rename variables so I can work with them
		tempname rvar

		if "`exp'"!="" ren (`varlist' `over' `exp') (yvar_ xvar_ over_ wgt)
		else {
			ren (`varlist' `over' ) (yvar_ xvar_ over_ )
			qui:gen byte wgt=1
		}
		** Continue or Modify data
		bysort over_ xvar_:gen n=_N
		sum n, meanonly
		** Pesos solo para sacar sumas o means
		** If more than 1 observation. then collapse
		if `r(max)'>1 & "`sum'"!="" {
			collapse (sum) yvar_ [iw=wgt], by(over_ xvar_)	fast
			gen byte wgt=1
			}

		** Get Range
		_rangevar xvar_, radj(`radj') nobs(`nobs') rvar(rvar) offset(`offset') range(`range')
		local vmin = r(vmin)
		local vmin2 = r(vmin2)
		local vmax = r(vmax)
		local vmax2 = r(vmax2)
		** get totals

		******************************************************************************************************************
		** S3: First pass BWs
		levelsof over_, local(lvl)

		if "`bwadj3'"=="" {

			local bwmean = 0
			local cn     = 0
			** S4 Pass over ALL possible values
			foreach i of local lvl {
				local cn = `cn'+1
				lpoly yvar_ xvar_ if over_==`i' [aw=wgt]  , kernel(`kernel')   nograph degree(`degree')
				local bw`cn' = r(bwidth)
				if `bwmean'==0 local bwmean = r(bwidth)
				else local bwmean = `bwmean'*(`cn'-1)/`cn'+r(bwidth)/`cn'
			}

		** And Recalculate. Between individual and average
			local cn     = 0
			foreach i of local lvl {
				local cn = `cn'+1
				local bw`cn' =`bwadj2'*(`bwadj'*`bw`cn''+(1-`bwadj')*`bwmean')
			}
		}

		if "`bwadj3'"!="" {
			local cn     = 0

			foreach i of local lvl {
				*display in w "`bwadj3'"
				local cn = `cn'+1
				local bw`cn' =`bwadj3'
			}
		}

		** s5: get initial smooth
		*****************************************************************************************************************
		local cn     = 0
		local fmax   = 0

		** First get densities and find the MAX
		foreach i of local lvl {
			local cn     = `cn'+1
			tempvar f`cn'
 			lpoly yvar_ xvar_ if over_==`i' [aw=wgt] , gen(`f`cn'') kernel(`kernel') at(rvar) bw(`bw`cn'') nograph degree(`degree')
			replace `f`cn''=0 if `f`cn''<0
			qui:sum `f`cn'', meanonly
			if r(max)>`fmax' local fmax = r(max)
		}

		if "`stack'`stack100'`stream'`stream1'"!="" local fmax=1
		if "`gap0'"=="" local gp=1
		else     {
			local fmax=1
			local gp=0
		}
		local vm 1

		** only what is needed
		keep if rvar!=.
		******************************************************************************************************************* s5: Rescale Densities if necessary

		if "`normalize'"!="" {
 			foreach i of local lvl {
				local cnx     = `cnx'+1
				sum  `f`cnx'', meanonly
				replace `f`cnx''=`f`cnx''/r(max)
			}
			local fmax=1
		}

		local cnt = `cn'
		local cn = 0


			foreach i of local lvl {
				local cn     = `cn'+1
				*display in w "qui: replace `f`cn''=(`f`cn''/`fmax') * `dadj'/`cnt' + 1/`cnt'*(`cnt'-`cn')*`gp'"
				qui: replace `f`cn''=(`f`cn''/`fmax') * `dadj'/`cnt' + 1/`cnt'*(`cnt'-`cn')*`gp'
				tempvar f0`cn'
				gen `f0`cn'' = 1/`cnt' * (`cnt'-`cn') * `gp'        if rvar!=.
			}


		** s6: Rescale Densities if necessary by graphtype
		****************************
		if "`stack'"!="" {
			local cn 0
			tempvar f00 f0 f01
			gen `f00'=0
			gen `f01'=0
			gen `f0'=0
			foreach i of local lvl {
				local cn_1   = `cn'
				local cn     = `cn'+1
				if `cn'>1 {
					qui: replace `f`cn''=`f`cn_1''+`f`cn''
					tempvar f0`cn'
					gen `f0`cn'' =`f`cn_1''         if rvar!=.
				}

			}
		}
		else if "`stack100'"!=""{
			local cn 0
			foreach i of local lvl {
				local cn     = `cn'+1
				local tvlist  `tvlist' `f`cn''
			}
			tempvar total
			egen `total'=rowtotal(`tvlist')

			local cn 0
			foreach i of local lvl {
				local cn     = `cn'+1
				replace `f`cn''=`f`cn''/`total'*100
			}

			local cn 0
			tempvar f00 f01 f0
			gen `f00'=0
			gen `f01'=0
			gen `f0'=0
			foreach i of local lvl {
				local cn_1   = `cn'
				local cn     = `cn'+1
				if `cn'>1 {
					qui: replace `f`cn''=`f`cn_1'' +`f`cn''
					tempvar f0`cn'
					gen `f0`cn'' =`f`cn_1''         if rvar!=.
				}
			}

		}
		tempvar x
		qui:gen `x'=.

		if "`stream'`stream1'"!=""{
			if "`stream'"!="" {
				replace `x'=`f`cnt''*.5
				local cn
				foreach i of local lvl {
					local cn = `cn'+1
					replace `f`cn''=`f`cn''-`x'
					replace `f0`cn''=`f0`cn''-`x'
				}
			}
			if "`stream1'"!="" {
				local cn
				local cnt2 = min(`stream1',`cnt')
				local cnt3 = `cnt2'-1
				if "`half'"=="" 	replace `x'=`f`cnt2''
				if "`half'"!="" 	replace `x'=`f`cnt3''+0.5*(`f`cnt2''-`f`cnt3'')
				foreach i of local lvl {
					local cn = `cn'+1
					replace `f`cn''=`f`cn''-`x'
					replace `f0`cn''=`f0`cn''-`x'
				}
			}
		}


		*******************************************************************************************
		** Text to identify What something is.
		** 1 Not valid if violin or gap0
		if "`text'"=="" & "`gap0'"=="" & "`stack'`stack100'`stream'`stream1'"=="" {
			local cn = 0
			foreach i of local lvl {
				local cn     = `cn'+1
				local lbl: label (over_) `i', `strict'
				if "`right'"=="" local totext `totext' `=`f0`cn''+0.5/`cnt'' `vmin2'  `"`lbl'"'
				else             local totext `totext' `=`f0`cn''+0.5/`cnt'' `vmax2'  `"`lbl'"'
			}
		}
		** how to write text?

		** Auto Legend
		if "`alegend'"!="" {
			local cn = 1

			foreach i of local lvl {
				local lbl: label (over) `i', `strict'
				local aleg `aleg' `cn' `"`lbl'"'
				local cn     = `cn'+1
			}
		}
		** colors
		local wcp: word count `colorpalette'
		if `wcp'>0 {
			if strpos( `"`colorpalette'"' , ",") == 0 local colorpalette `"`colorpalette' , nograph n(`cnt')"'
			else local colorpalette `"`colorpalette'  nograph n(`cnt')"'
			colorpalette `colorpalette'
			** Putting all together
			local cn = 0
			foreach i of local lvl {
				local cn = `cn'+1
				local ll:word `cn' of `r(p)'

				local joy `joy' (rarea `f`cn'' `f0`cn'' rvar, color(`"`ll'"') ///
								`fcolor' `fintensity' `lcolor' `lwidth' `lpattern' `lalign' `lstyle' `horizontal')
			}
		}
		else if `"`color'"'!="" {
			local cn = 0

			foreach i of local lvl {
				local cn = `cn'+1
				if `cn'<=`:word count `color'' 	local ll:word `cn' of `color'
				local joy `joy' (rarea `f`cn'' `f0`cn'' rvar,  `lcolor' `lwidth' color(`"`ll'"') ///
								`fcolor' `fintensity' `lcolor' `lwidth' `lpattern' `lalign' `lstyle' `horizontal')
			}
		}
		else {
				local cn = 0
				local cn2 = 0
				foreach i of local lvl {
				local cn = `cn'+1
				local cn2 = `cn2'+1
				if `cn2'>15 local cn2 = 1
				local joy `joy' (rarea `f`cn'' `f0`cn'' rvar,  ///
								`fcolor' `fintensity' `lcolor' `lwidth' `lpattern' `lalign' `lstyle' ///
								 pstyle(p`cn2') `horizontal')
			}
		}
		***************************************************************************************************************
		if "`alegend'"!="" local leg   legend(order(`aleg'))
		else if strpos( "`options'" , "legend")==0 local leg legend(off)
		else local leg
 		if "`gap0'"!="" | "`stack'`stack100'`stream'`stream1'"!=""  local ylabx
		else local ylabx ylabel("")

		two `joy' (`addplot'), ///
			text(`totext' , `textopt') ///
			`options' `leg' `ylabx' `xlabvio'

	}


end