capture program drop cfa
program cfa,rclass
syntax varlist, PARTition(numlist integer >0) [SCOrename(string) CFAMethod(string) CFAStand]


local C = 0
foreach z in `partition' {
	local C = `C' + `z'
}

local nbvars : word count `varlist'
if `C' != `nbvars' {
	di in red "The sum of the numbers in the partition option is different from the number of variables precised in varlist"
	exit
}

local P:word count `partition'
if "`scorename'" !="" {
	local S:word count `scorename'
	if `P'!=`S' {
		di in red "The number of score names given is different from the number of dimensions in the partition option"
		exit
	}
}

local i = 1
foreach x in `varlist' {
	local var`i' = "`x'"
	local `++i'
}

local name
local nname
if "`scorename'"=="" {
	forvalues i = 1/`P' {
		local name "Dim`i'"
		local nname `nname' `name'
	}
local scorename = "`nname'"
}

local upscorename = upper("`scorename'")

*capture calcscore `varlist', scorename(`upscorename') partition(`partition')

local i = 0
local y = 1
tokenize `upscorename'
foreach x in `partition' {
	local `i++'
	if `i' == 1 local s = `x'
	else local s = `s' +`x'

	local liste = ""
	forvalues w = `y'/`s' {
		local liste `liste' `var`w''
	}

	local a =  "(``i'' -> `liste')"
	local z `z' `a'

	local y = `s'+1
}
/*
local cpt = 0
if "`cfa_ml'" != "" {
	local method = "ml"
	local cpt `cpt' + 1
}
if "`cfa_mlmv'" != "" {
	local method = "mlmv"
	local cpt `cpt' + 1
}
if "`cfa_adf'" != "" {
	local method = "adf"
	local cpt `cpt' + 1
}
else local method = "ml"
if `cpt'>1 {
	di in red "You must choose between cfa_ml, cfa_mlmv or cfa_adf (the options are exclusive)"
	exit 119
}
*/


if "`cfamethod'" == "" local cfamethod = "ml"

if "`cfamethod'" != "ml" & "`cfamethod'" != "mlmv" & "`cfamethod'" != "adf" {
	di "`cfamethod'"
	di in red "option cfamethod incorrectly specified (choose among ml, mlmv and adf)"
	error 198
}


if "`cfastand'" != "" local cfastand = "stand"

di as result "{hline}"
di "{bf:Confirmatory factor analysis}"
di as result "{hline}"
di

qui sem `z', method(`cfamethod') `cfastand'

/*
sem (HA -> ioc1-ioc4) (PSE -> ioc5-ioc8) (W -> ioc9-ioc15) ///
(BCC -> ioc16-ioc18) (AC -> ioc19-ioc21) (AE -> ioc22-ioc25) ///
(LI -> ioc26-ioc32) (MOC -> ioc33-ioc37)
,stand
cov(e.ioc36*e.ioc37
e.ioc28*e.ioc29 e.ioc14*e.ioc15 e.ioc23*e.ioc25 e.ioc33*e.ioc34 ///
e.ioc9*e.ioc10 e.ioc6*e.ioc8 e.ioc5*e.ioc7) // method(mlmv)
*/

/* factor loadings */

matrix r = r(table)
matrix r = r[1,1...]
matrix r = r'
local n = `nbvars'*2

matrix a = r[1,1]
forvalues i=3(2)`n' {
	matrix b = r[`i',1]
	matrix a = a\b
}

/* standard error */

matrix r = r(table)
matrix r = r[2,1...]
matrix r = r'
local n = `nbvars'*2

matrix se = r[1,1]
forvalues i=3(2)`n' {
	matrix b = r[`i',1]
	matrix se = se\b
}


/* intercepts */

matrix r = r(table)
matrix r = r[1,1...]
matrix r = r'
local n = `nbvars'*2

matrix a2 = r[2,1]
forvalues i=4(2)`n' {
	matrix b = r[`i',1]
	matrix a2 = a2\b
}

/* variances des erreurs */

local m = `n'+1
matrix r = r(table)
matrix r = r[1,`m'...]
matrix r = r'

matrix a3 = r[1,1]
forvalues i=2/`nbvars' {
	matrix b = r[`i',1]
	matrix a3 = a3\b
}

/* variance des dimensions*/

matrix r = r(table)
local n = `nbvars'*3+1
matrix r = r[1,`n'...]
matrix r = r'

matrix var = r[1,1]
forvalues i=2/`P' {
	matrix b = r[`i',1]
	matrix var = var\b
}


local i = 1
foreach v in `varlist' {
	local var`i' = abbrev("`v'",10)
	local `++i'
}


local i = 1
foreach s in `scorename' {
	local s`i' = abbrev("`s'",10)
	local sc `sc' `s`i''
	local `++i'

}

local max = 10
local dec = `max'+5

local max2 = 10

local dec2 = `dec'+`max2'+5

local a = e(N)
di "{text:Number of used individuals: `a'}"
di
di _col(`=`dec2'+17+4') "{bf:Estimation:}"


di as result "{bf:Item}" _c
di _col(`dec') "{bf:Dimension}" _c
*local col = `dec'+17
di _col(`dec2') "{bf:Factor}" _c
*local col = `dec2'+17
di _col(`=`dec2'+14') "{bf:Standard}" _c
*local col = `col'+17
di _col(`=`dec2'+28') "{bf:Intercept}" _c
*local col = `col'+13


if "`cfastand'" == "" {
	di _col(`=`dec2'+42') "{bf:Variance of}" _c
	di _col(`=`dec2'+56') "{bf:Variance of}"

	di _col(`dec2') "{bf:loading}" _c
	*local col = `dec2'+17
	di _col(`=`dec2'+14') "{bf:error}" _c
	*local col = `col'+30

	di _col(`=`dec2'+42') "{bf:error}" _c
	di _col(`=`dec2'+56') "{bf:dimension}"
	local h = `dec2'+66
}
else {
	di _col(`=`dec2'+42') "{bf:Variance of}"

	di _col(`dec2') "{bf:loading}" _c
	*local col = `dec2'+17
	di _col(`=`dec2'+14') "{bf:error}" _c
	*local col = `col'+30

	di _col(`=`dec2'+42') "{bf:errors}"
	local h = `dec2'+52
}


di "{hline `h'}"

local i = 1
local y = 1
foreach x in `partition' {
	if `i' == 1 local s = `x'
	else local s = `s' +`x'

	forvalues z = `y'/`s' {
		tokenize `sc'
		di "{bf:`var`z''}"_c
		di _col(`dec') "{bf:``i''}" _c
		local t = a[`z',1]
		local t : di %7.2f `t'
		*local col = `dec'+17
		di _col(`dec2') "{text:`t'}" _c

		local t = se[`z',1]
		local t : di %8.2f `t'
		*local col = `dec2'+9
		di _col(`=`dec2'+14') "{text:`t'}" _c

		local t = a2[`z',1]
		local t : di %9.2f `t'
		*local col = `col'+17
		di _col(`=`dec2'+28') "{text:`t'}" _c

		local t = a3[`z',1]
		local t : di %11.2f `t'
		*local col = `col'+13


		if "`cfastand'" == "" & `z' == `y'{
			di _col(`=`dec2'+42') "{text:`t'}" _c
			local t = var[`i',1]
			local t : di %11.2f `t'
			*local col = `dec2'+17+17+13+14
			di _col(`=`dec2'+56') "{text:`t'}"
		}
		else di _col(`=`dec2'+42') "{text:`t'}"
	}
	di
	local `i++'
	local y = `s'+1
}

qui estat gof, stats(all)

local chi2 = r(chi2_ms)
local p = r(p_ms)
local ddl = r(df_ms)
local ratio = `chi2'/`ddl'
local rmsea = r(rmsea)
local lb = r(lb90_rmsea)
local ub = r(ub90_rmsea)
local nfi = 1-(r(chi2_ms)/r(chi2_bs))
local rni = 1-(r(chi2_ms)-r(df_ms))/(r(chi2_bs)-r(df_bs))
local cfi = r(cfi)
local ifi = (r(chi2_bs)-r(chi2_ms))/(r(chi2_bs)-r(df_ms))
local mci = exp(-0.5*((r(chi2_ms)-r(df_ms))/(e(N)-1)))
local srmr = r(srmr)

di
di "{bf:Goodness of fit}"
di

di as result _col(4) "chi2" _c
di as result _col(20) "ddl" _c
di as result _col(28) "chi2/ddl" _c
di as result _col(42) "RMSEA [90% CI]" _c
di as result _col(64) "SRMR" _c
di as result _col(74) "NFI" _c
di as result _col(84) "RNI" _c
di as result _col(94) "CFI" _c
di as result _col(104) "IFI" _c
di as result _col(114) "MCI"

*di as result "`P' dimensions" _c

local t : di %7.2f `chi2'
di "{text:`t'}" _c
local t : di %3.0f `ddl'
di _col(20) "{text:`t'}" _c
local t : di %7.1f `ratio'
di _col(29) "{text:`t'}" _c
local t : di %5.3f `rmsea'
local l : di %5.3f `lb'
local u : di %5.3f `up'
di _col(40) "{text:`t' [`l' ; `u']}" _c
local t : di %5.3f `srmr'
di _col(63) "{text:`t'}" _c
local t : di %5.3f `nfi'
di _col(72) "{text:`t'}" _c
local t : di %5.3f `rni'
di _col(82) "{text:`t'}" _c
local t : di %5.3f `cfi'
di _col(92) "{text:`t'}" _c
local t : di %5.3f `ifi'
di _col(102) "{text:`t'}" _c
local t : di %5.3f `mci'
di _col(112) "{text:`t'}"
local p : di %5.3f `p'
di "{text:(p-value = `p')}"
di as result


/*
matrix ind = (`chi2',`ddl',`ratio',`rmsea',`nfi',`rni',`cfi',`ifi',`srmr')
matrix colnames ind = "chi2" "ddl" "chi2/ddl" "RMSEA" "NFI" "RNI" "CFI" "IFI" "SRMR"
matrix rownames ind = ""
di
di "{bf:Goodness of fit}"
matrix list ind, format(%6.3f) noheader
*/
end

*cfa ioc1-ioc37, partition(4 4 7 3 3 4 7 5) scorename(HAaaaaaaaaaaaaaaaaaaaaaaaaaz PSE W BCC AC AE LI MOC) cfamethod(ml) //cfastand
*cfa x1-x40, partition(5 5 5 5 5 5 5 5) cfastand