import org.doomedsociety.gradlecpp.cfg.BinaryKind
import org.doomedsociety.gradlecpp.msvc.CallingConvention
import org.doomedsociety.gradlecpp.msvc.CodeGenerationKind
import org.doomedsociety.gradlecpp.msvc.CppExceptions
import org.doomedsociety.gradlecpp.msvc.DebugInfoFormat
import org.doomedsociety.gradlecpp.msvc.EnhancedInstructionsSet
import org.doomedsociety.gradlecpp.msvc.ErrorReporting
import org.doomedsociety.gradlecpp.msvc.FloatingPointModel
import org.doomedsociety.gradlecpp.msvc.LinkTimeCodeGenKind
import org.doomedsociety.gradlecpp.msvc.MsvcToolchainConfig
import org.doomedsociety.gradlecpp.msvc.OptimizationLevel
import org.doomedsociety.gradlecpp.msvc.RuntimeChecks
import org.doomedsociety.gradlecpp.msvc.WarningLevel

rootProject.ext.createMsvcConfig = { boolean release, BinaryKind binKind ->
	MsvcToolchainConfig cfg
	if (release) {
		cfg = new MsvcToolchainConfig(
				compilerOptions: new MsvcToolchainConfig.CompilerOptions(
						codeGeneration: CodeGenerationKind.MULTITHREADED,
						optimizationLevel: OptimizationLevel.FULL_OPTIMIZATION,
						debugInfoFormat: DebugInfoFormat.PROGRAM_DATABASE,
						runtimeChecks: RuntimeChecks.DEFAULT,
						cppExceptions: CppExceptions.ENABLED_WITH_SEH,
						warningLevel: WarningLevel.LEVEL_3,
						callingConvention: CallingConvention.CDECL,
						enhancedInstructionsSet: EnhancedInstructionsSet.SSE2,
						floatingPointModel: FloatingPointModel.FAST,

						enableMinimalRebuild: false,
						omitFramePointers: false,
						wholeProgramOptimization: true,
						enabledFunctionLevelLinking: true,
						enableSecurityCheck: true,
						analyzeCode: false,
						sdlChecks: false,
						treatWarningsAsErrors: false,
						treatWchartAsBuiltin: true,
						forceConformanceInForLoopScope: true,

						extraDefines: [
								'WIN32': null,
								'_MBCS': null,
								'NDEBUG': null,
						]
				),

				linkerOptions: new MsvcToolchainConfig.LinkerOptions(
						linkTimeCodeGenKind: LinkTimeCodeGenKind.USE_LTCG,
						errorReportingMode: ErrorReporting.NO_ERROR_REPORT,

						enableIncrementalLinking: false,
						eliminateUnusedRefs: true,
						enableCOMDATFolding: true,
						generateDebugInfo: true,
						dataExecutionPrevention: true,
						randomizedBaseAddress: true
				),

				librarianOptions: new MsvcToolchainConfig.LibrarianOptions(
						linkTimeCodeGenKind: LinkTimeCodeGenKind.USE_LTCG
				),

				generatePdb: true
		)
	} else {
		//debug
		cfg = new MsvcToolchainConfig(
				compilerOptions: new MsvcToolchainConfig.CompilerOptions(
						codeGeneration: CodeGenerationKind.MULTITHREADED_DEBUG,
						optimizationLevel: OptimizationLevel.DISABLED,
						debugInfoFormat: DebugInfoFormat.PROGRAM_DATABASE,
						runtimeChecks: RuntimeChecks.DEFAULT,
						cppExceptions: CppExceptions.ENABLED_WITH_SEH,
						warningLevel: WarningLevel.LEVEL_3,
						callingConvention: CallingConvention.CDECL,
						enhancedInstructionsSet: EnhancedInstructionsSet.SSE2,
						floatingPointModel: FloatingPointModel.FAST,

						enableMinimalRebuild: true,
						omitFramePointers: false,
						wholeProgramOptimization: false,
						enabledFunctionLevelLinking: true,
						enableSecurityCheck: true,
						analyzeCode: false,
						sdlChecks: false,
						treatWarningsAsErrors: false,
						treatWchartAsBuiltin: true,
						forceConformanceInForLoopScope: true,

						extraDefines: [
								'WIN32': null,
								'_MBCS': null,
								'_DEBUG': null,
						]
				),

				linkerOptions: new MsvcToolchainConfig.LinkerOptions(
						linkTimeCodeGenKind: LinkTimeCodeGenKind.DEFAULT,
						errorReportingMode: ErrorReporting.NO_ERROR_REPORT,

						enableIncrementalLinking: true,
						eliminateUnusedRefs: false,
						enableCOMDATFolding: false,
						generateDebugInfo: true,
						dataExecutionPrevention: true,
						randomizedBaseAddress: true
				),

				librarianOptions: new MsvcToolchainConfig.LibrarianOptions(
						linkTimeCodeGenKind: LinkTimeCodeGenKind.USE_LTCG
				),

				generatePdb: true
		)

		if (binKind == BinaryKind.STATIC_LIBRARY) {
			cfg.compilerConfig.extraDefines['_LIB'] = null
		}
	}

	return cfg
}