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
}