// LESSBranchCompiler compiles individual branches of the Go source tree into selective CSS files
func LESSBranchCompiler(lessBranchOptions codeutilsShared.LESSBranchOptions) {
	lessCompileFlags := []string{
		"--clean-css", // Clean the CSS (such as minification, comment removal, so forth)
		"--no-color",
		"--no-ie-compat", // Disable IE Compatibility
		"--no-js",
		"--strict-math=on", // Do not process math
	}

	if lessBranchOptions.UseGlob { // If  we should use globbing
		lessCompileFlags = append(lessCompileFlags, []string{"--glob"}...) // Provide --glob
	}

	if len(lessBranchOptions.AdditionalCompileOptions) != 0 { // If there was Additional Compile Options to pass
		lessCompileFlags = append(lessCompileFlags, lessBranchOptions.AdditionalCompileOptions...)
	}

	writeFileName, _ := codeutilsShared.FindClosestFile("src/less/" + lowercaseProjectName + ".less") // Define writeFileName as the file name we'll be compiling

	lessCompileFlags = append(lessCompileFlags, []string{writeFileName}...)
	commandOutput := codeutilsShared.ExecCommand("lessc", lessCompileFlags, false) // Run the less compiler

	errorIndex := strings.Index(commandOutput, "Error")
	if (errorIndex > 12) || (errorIndex == -1) { // If there was no initial error (any error string beyond a certain point should be assumed to be a part of the program)
		uniqueFileName := strings.Replace(filepath.Base(writeFileName), ".less", "", -1)
		if lessBranchOptions.UniqueHash { // If we should be using a unique hash
			uniqueFileName += "-" + codeutilsShared.Sha512Sum(commandOutput, 1)[0:12] // Append first 12 characters of hash
		}

		uniqueFileName += ".css"                                                                                             // Append .css
		codeutilsShared.WriteOrUpdateFile("build/"+uniqueFileName, []byte(commandOutput), codeutilsShared.UniversalFileMode) // Write to build folder
		codeutilsShared.CopyFile("build/"+uniqueFileName, "tests/design/css/"+uniqueFileName)                                // Copy from build folder to css folder
	} else {
		fmt.Println(commandOutput)
	}
}
// CompileTypeScript compiles Typescript into Javascript and ensure JavaScript is minified and optimized
func CompileTypeScript() error {
	var compileError error

	if codeutilsShared.ExecutableExists("tsc") { // If the tsc executable exists
		if codeutilsShared.IsDir("src/typescript") { // If src/typescript is a valid directory
			if !strings.HasPrefix(projectConfig.TypeScript.Target, "ES") { // If it either an empty string or does not begin with ES
				projectConfig.TypeScript.Target = "ES5" // Default to ES5
			}

			typescriptFileName, _ := codeutilsShared.FindClosestFile("src/typescript/" + lowercaseProjectName + ".ts") // Define typescriptFileName as the closest file name to the one we're providing
			baseFileName := strings.Replace(filepath.Base(typescriptFileName), ".ts", "", -1)                          // Set baseFileName to typescript file name but with .ts removed

			typescriptCompileFlags := []string{ // Define typescriptCompileFlags as the following options
				"--declaration",                              // Create a declaration file
				"--forceConsistentCasingInFileNames",         // Enforce consistency in file names
				"--noFallthroughCasesInSwitch",               // Disallow fallthrough cases in switches
				"--noImplicitReturns",                        // Disallow implicit returns
				"--outFile", "build/" + baseFileName + ".js", // Output a single JS file in the build dir
				"--removeComments",                          // Remove comments
				"--target", projectConfig.TypeScript.Target, // Set the target
				typescriptFileName, // Append the .ts name
			}

			commandOutput := codeutilsShared.ExecCommand("tsc", typescriptCompileFlags, false) // Call execCommand and get its commandOutput

			if !strings.Contains(commandOutput, "error TS") { // If tsc did not report any errors
				if projectConfig.TypeScript.MinifyContent { // If we should minify the content
					minifyFailure := MinifyJavaScript() // Call the minification func, set any error to minifyFailure

					if minifyFailure == nil { // If there was no error minifying
						minifyFileName := baseFileName + ".min.js"

						if projectConfig.TypeScript.UseLibreJSHeader && (projectConfig.TypeScript.LibreJSLicense != "") { // If we should use the LibreJSHeader and the license value is set
							var finalMinifiedContent string // Define finalMinifiedContent as the content we get from AddLicense

							finalMinifiedContent, compileError = librejsgopher.AddLicense(projectConfig.TypeScript.LibreJSLicense, "build/"+minifyFileName, true) // Add the requested license to the JS file, return content

							if (compileError == nil) && projectConfig.TypeScript.UniqueHash { // If there was no issue adding the license and we should be using a unique hash
								uniqueFileName := baseFileName + "-" + codeutilsShared.Sha512Sum(finalMinifiedContent, 1)[0:12] + ".min.js" // Append first 12 characters of hash
								os.Rename("build/"+minifyFileName, "build/"+uniqueFileName)                                                 // Move the file to one with a unique file name
								minifyFileName = uniqueFileName                                                                             // Change minifyFileName to uniqueName
							}
						}

						if projectConfig.UsesTests { // If we are using tests
							compileError = codeutilsShared.CopyFile("build/"+baseFileName+".js", "tests/design/js/"+baseFileName+".js") // Copy over the non-minified JS to the test js folder
							compileError = codeutilsShared.CopyFile("build/"+minifyFileName, "tests/design/js/"+minifyFileName)         // Copy over the minified JS from build to the test js folder
						}
					} else { // If there was an error minifying
						compileError = minifyFailure // Set compileError to the minifyFailure
					}
				}
			} else { // If tsc did report errors
				compileError = errors.New(commandOutput) // Set compileError to the commandOutput
			}
		} else { // If src/typescript is not a valid directory
			compileError = errors.New("typescript" + dirDoesNotExistInSrc)
		}
	} else { // If the typescript compiler is not installed on this system
		compileError = errors.New("tsc" + executableNotInstalled)
	}

	return compileError
}