********************************************************************************
* Description of the Program -												   *
* This program is used to set theme values for things like backgrounds, point  *
* sizes, font sizes, etc...   The purpose is to allow the end user greater	   *
* flexibility in developing graph themes (e.g., create a ggplot2 theme with    *
* a given set of palettes and also create a theme with a more Tufte inspired   *
* set of background/size parameters). 										   *
*                                                                              *
* Data Requirements -														   *
*	  Allows users to build the property file interactively					   *
*																			   *
* System Requirements -														   *
*     none                                                                     *
*                                                                              *
* Program Output -                                                             *
*     theme-[theme file name].theme - The theme file created by the user	   *
*	  theme-[theme file name]_achromatopsia.theme - Full Colorblind version	   *
*	  theme-[theme file name]_protanopia.theme - Full Colorblind version	   *
*	  theme-[theme file name]_deuteranopia.theme - Full Colorblind version	   *
*	  theme-[theme file name]_tritanopia.theme - Full Colorblind version	   *
*                                                                              *
* Lines -                                                                      *
*     391                                                                      *
*                                                                              *
********************************************************************************

*! brewtheme
*! v 1.0.0
*! 21MAR2016

// Drop the program from memory if loaded
cap prog drop brewtheme

// Define program
prog def brewtheme

	// Set version to interpret under
	version 13.1

	// Set syntax tree
	syntax [anything(name=themefile id="Theme File Name")] [,				 ///
						ABOvebelow(string asis) ANGLESTYle(string asis)		 ///
						AREASTYle(string asis) ARROWSTYle(string asis)		 ///
						AXISSTYle(string asis) BARLABELPos(string asis)		 ///
						BARLABELSTYle(string asis) BARSTYle(string asis)	 ///
						BYGRAPHSTYle(string asis) CLEGENDSTYle(string asis)	 ///
						CLOCKdir(string asis) COLor(string asis)			 ///
						COMPASS2dir(string asis) COMPASS3dir(string asis)	 ///
						CONNECTSTYle(string asis) DOTTYPESTYle(string asis)	 ///
						GRAPHSIze(string asis) GRAPHSTYle(string asis)		 ///
						GRIDLINESTYle(string asis) GRIDRINGSTYle(string asis) ///
						GRIDSTYle(string asis) GSIZE(string asis) 			 ///
						HORIZontal(string asis) LABELSTYle(string asis)		 ///
						LEGENDSTYle(string asis) LINEPATtern(string asis)	 ///
						LINESTYle(string asis) LINEWidth(string asis)		 ///
						MARGin(string asis) MEDTYPESTYle(string asis)		 ///
						NUMSTYle(string asis) NUMTICKS(string asis)			 ///
						PIEGRAPHSTYle(string asis) PIELABELSTYle(string asis) ///
						PLOTREGIONSTYle(string asis) RELATIVEPos(string asis) ///
						RELSIze(string asis) SPECial(string asis)			 ///
						STARSTYle(string asis) SYMBol(string asis)			 ///
						SYMBOLSIze(string asis) SUNFLOWERSTYle(string asis)	 ///
						TEXTBOXSTYle(string asis) TICKPosition(string asis)  ///
						TICKSTYle(string asis) TICKSETSTYle(string asis)	 ///
						VERTICALText(string asis) YESNo(string asis) 		 ///
						ZYX2Rule(string asis) ZYX2STYle(string asis) 		 ///
						LOADThemedata brewscheme ]

	// Check for brewscheme Mata library
	qui: brewlibcheck

	// Stores the root file path for theme files
	loc themeroot `c(sysdir_personal)'b/theme/theme

	// Preserve the current state of the data
	preserve

		// Only initialize this mata class if program not called by brewscheme
		if `"`brewscheme'"' == "" {

			// Create a brewcolors object
			mata: brewc = brewcolors()

		} // End IF Block to initialize brewcolors object

		// Get the list of unique meta names
		qui: mata: brewc.getNames(1, 1)

		// Build dataset with classes, arguments, and parameter values
		qui: themedata

		// Store the name of the tempfile
		loc tmptheme `r(themefile)'

		// Load the tempfile
		qui: use `tmptheme', clear

		// Loop over the class names
		foreach v in `"`r(classes)'"' {

			// Store arguments in new locals
			loc `v'args `"`r(``v'args')'"'

			// If the user passed values
			if `"``v''"' != "" {

				// Loop over arguments
				forv i = 1/`: word count ``v''' {

					// Store argument
					loc indi `: word `i' of ``v'''

					loc arg `: word 1 of `indi''

					loc val `: word 2 of `indi''

					// Block used to handle cases with unbalanced quotation marks
					// in the value of the key-value pair.
					if 	substr(`"`val'"', 1, 1) != `"""' & 					 ///
						substr(`"`val'"', -1, 1) == `"""' {

						// If the first character isn't a " but the last
						// character is a " replace all instances of " with
						// nothing in the value string
						loc val `: subinstr loc val `"""' "", all'

					} // End IF Block for unbalanced quotation mark handling

					// Check if valid argument
					if `"`: list arg in `v'args'"' != "" {

						// Search for the RGB values
						qui: mata: brewc.brewNameSearch("`val'")

						foreach x in rgb achromatopsia protanopia deuteranopia tritanopia {

							if `"``x''"' == "" loc `x' none

						}

						// Check for named color style
						if `: list val in colornames' == 1 {

							// Replace value with user specified value
							qui: replace value = `"`val'"' if 				 ///
							classname == `"`v'"' & argname == `"`arg'"'

							// Populate color blind variables
							qui: replace achromatopsia = `"`val'_achromatopsia"' ///
							if classname == `"`v'"' & argname == `"`arg'"'

							// Populate red colorblindness
							qui: replace protanopia = `"`val'_protanopia"' if	 ///
							classname == `"`v'"' & argname == `"`arg'"'

							// Populate red colorblindness
							qui: replace deuteranopia = `"`val'_deuteranopia"' ///
							if classname == `"`v'"' & argname == `"`arg'"'

							// Populate red colorblindness
							qui: replace tritanopia = `"`val'_tritanopia"' if	 ///
							classname == `"`v'"' & argname == `"`arg'"'

						} // End IF Block for color value

						// Check to see if the value was a color
						else if `"`val'"' != `"`rgb'"' &					 ///
						`: list val in colornames' == 0 {

							// Replace value with user specified value
							qui: replace value = `""`rgb'""' if 			 ///
							classname == `"`v'"' & argname == `"`arg'"'

							// Populate color blind variables
							qui: replace achromatopsia = `""`achromatopsia'""' ///
							if classname == `"`v'"' & argname == `"`arg'"'

							// Populate red colorblindness
							qui: replace protanopia = `""`protanopia'""' if	 ///
							classname == `"`v'"' & argname == `"`arg'"'

							// Populate red colorblindness
							qui: replace deuteranopia = `""`deuteranopia'""' ///
							if classname == `"`v'"' & argname == `"`arg'"'

							// Populate red colorblindness
							qui: replace tritanopia = `""`tritanopia'""' if	 ///
							classname == `"`v'"' & argname == `"`arg'"'

						} // End ELSEIF Block for color value

						// For non color values
						else {

							// Replace value with user specified value
							qui: replace value = `"`rgb'"' if 				 ///
							classname == `"`v'"' & argname == `"`arg'"'

							// Populate color blind variables
							qui: replace achromatopsia = `"`achromatopsia'"' ///
							if classname == `"`v'"' & argname == `"`arg'"'

							// Populate red colorblindness
							qui: replace protanopia = `"`protanopia'"' if	 ///
							classname == `"`v'"' & argname == `"`arg'"'

							// Populate red colorblindness
							qui: replace deuteranopia = `"`deuteranopia'"' if ///
							classname == `"`v'"' & argname == `"`arg'"'

							// Populate red colorblindness
							qui: replace tritanopia = `"`tritanopia'"' if	 ///
							classname == `"`v'"' & argname == `"`arg'"'

						} // End ELSE Block for non color values

					} // End IF Block for valid arguments

				} // End Loop over arguments

			} // End IF Block for user supplied values

		} // End Loop over class names

		// Save changes to the tempfile
		qui: save `tmptheme', replace

		// Check for name of themefile
		if `"`themefile'"' != "" {

			// Check for directory and if not build it
			dirfile, p(`"`c(sysdir_personal)'b/theme"')

			// Write the scheme file to a location on the path
			qui: file open theme using `"`themeroot'-`themefile'.theme"', w replace

			// Loop over colorblind variables
			foreach cb in achromatopsia protanopia deuteranopia tritanopia {

				// Open a theme file for each of the colorblind types
				qui: file open `cb'theme using 								 ///
				`"`themeroot'-`themefile'_`cb'.theme"', w replace

			} // End Loop to open color blindness theme files

			// Call write subroutine
			themewriter

		} // End IF BLock for writing a theme file if user specified a theme file name

		// If no name is passed write the default file
		else {

			// Check for directory and if not build it
			dirfile, p(`"`c(sysdir_personal)'b/theme"')

			// Write the scheme file to a location on the path
			qui: file open theme using `"`themeroot'-default.theme"', w replace

			// Loop over colorblind variables
			foreach cb in achromatopsia protanopia deuteranopia tritanopia {

				// Open a theme file for each of the colorblind types
				qui: file open `cb'theme using 								 ///
				`"`themeroot'-default_`cb'.theme"', w replace

			} // End Loop to open color blindness theme files

			// Call write subroutine
			themewriter

		} // End else block for a default theme file

	// Restore the data to the original state
	restore

	// Check loadthemedata option
	if `"`loadthemedata'"' != "" {

		// Load the tempfile
		qui: use `tmptheme', clear

	} // End IF Block for load theme data option

// End Program Definition
end

// Drop subroutine if already loaded in memory
cap prog drop themedata

// Subroutine to build look up dataset
prog def themedata, rclass

	// Null syntax structure
	syntax

	// Drop data from memory
	clear

	// Check for file
	cap confirm file `"`c(sysdir_plus)'b/brewthemedata.do"'

	// If does not exist
	if _rc != 0 {

		// Download the file from GitHub
		copy "http://wbuchanan.github.io/brewscheme/brewthemedata.do" 		 ///
		`"`c(sysdir_plus)'b/brewthemedata.do"'

	} // End IF Block for non-existent file

	// Run the do file
	qui: do `"`c(sysdir_plus)'b/brewthemedata.do"'

	// Reserve namespace for a temporary file
	tempfile themedata

	// Get the names of the classes that can have values altered
	qui: levelsof classname if substr(classname, 1, 1) != "*", loc(classes)

	// Return a local with the class names
	ret loc classes `classes'

	// Loop over the class names
	foreach v of loc classes {

		// Get the argument names for the classes
		qui: levelsof argname if classname == `"`v'"', loc(args)

		// Return the arguments for the given class
		ret loc `v'args `args'

	} // End Loop over the class names

	// Save the data to a temporary file
	qui: save `themedata'.dta, replace

	// Clear those data from memory
	clear

	// Return the name of the tempfile
	ret loc themefile `themedata'.dta

// End of the subroutine definition
end

// Drop subroutine if already loaded in memory
cap prog drop themewriter

// Subroutine for writing the data to a theme file
prog def themewriter

	// Null syntax structure
	syntax

	// Loop over the observations
	forv i = 1/`c(N)' {

		// Combine the different variables into a single string
		loc string `: di classnm[`i'] + argnm[`i'] + value[`i']'

		// Write the string to the file and insert the number of new
		// lines based on new line variable
		file write theme `"`"`string'"' `: di newlines[`i']'"' _n

		// Loop over the colorblindness types
		foreach cb in achromatopsia protanopia deuteranopia tritanopia {

			// Creates string with color bli
			loc string `: di classnm[`i'] + argnm[`i'] + `cb'[`i']'

			// Write to the colorblind simulated theme file
			file write `cb'theme `"`"`string'"' `: di newlines[`i']'"' _n

		} // End Loop over colorblind transformed theme files

	} // End Loop over observations

	// Close the open file connection
	file close theme

	// Loop over the colorblindness types
	foreach cb in achromatopsia protanopia deuteranopia tritanopia {

		// Close the theme file
		file close `cb'theme

	} // End loop over colorblindness type theme files

// End of sub routine
end