// Copyright 2023-2024 Gentoo Authors
// Distributed under the terms of the GNU General Public License v2

namespace Gdmt.Ebuild

module Private =
    open System
    open System.IO

    open SimpleLog.SimpleLog

    open Gdmt.Shared
    open Gdmt.Shared.Types

    let FindEbuildFiles (path: string) : StringArray =
        match path with
        | p when Directory.Exists p -> Directory.GetFiles(path, "*.ebuild")
        | p when File.Exists p -> [| p |]
        | _ -> $"The ebuild file does not exist, given {path}" |> Exception |> raise

    [<Struct>]
    type PortageSettings =
        { DoPerformTest: bool
          FEATURES: string
          USE: string }

        member this.GetTestFlag: string = if this.DoPerformTest then "test " else ""
        member this.GetAllowTest: string = if this.DoPerformTest then "all " else ""

        member this.GetFeatures: string = this.GetTestFlag + this.FEATURES
        member this.GetUse: string = this.GetTestFlag + this.USE

        member this.GetPortageEnv() : ProcessEnvironmentMap =
            [ ("ALLOW_TEST", this.GetAllowTest)
              ("FEATURES", this.GetFeatures)
              ("USE", this.GetUse) ]

    [<Struct>]
    type ProcessSettings =
        { Niceness: int
          Jobs: int
          LoadAverage: int }

    let RunEbuildCommands
        (ebuild: string)
        (ebuildCommands: StringArray)
        (envMap: ProcessEnvironmentMap)
        (niceness: int)
        : unit =
        let args =
            [ "nice"; "-n"; $"{niceness}"; "ebuild"; ebuild ]
            @ (ebuildCommands |> Array.toList)

        LogMessage Debug $"Running ebuild command for {ebuild}"

        try
            ExecProcess(args, envMap).Run().Check()

            LogMessage Success $"Ebuild command for {ebuild} finished successfully"
        with _ex ->
            LogMessage Error $"Ebuild command for {ebuild} failed"

            reraise ()

    let MakeCleanedEnvTuple (envVar: string) : EnvVarPair = (envVar, "")

    let EbuildCleanedEnvMap: EnvVarMap =
        [ "ANT_HOME"
          "ANT_RESPECT_JAVA_HOME"
          "CARGO_HOME"
          "CONAN_USER_HOME"
          "DBUS_SESSION_BUS_ADDRES"
          "DISPLAY"
          "GOPATH"
          "GPG_TTY"
          "GRADLE_USER_HOME"
          "HEX_HOME"
          "HOME"
          "ICEAUTHORITY"
          "IPYTHONDIR"
          "JULIA_DEPOT_PATH"
          "JUPYTER_CONFIG_DIR"
          "MIX_HOME"
          "NIMBLE_DIR"
          "NPM_CONFIG_USERCONFIG"
          "OPAMROOT"
          "PINENTRY_USER_DATA"
          "PIP_CACHE_DIR"
          "PYLINTHOME"
          "XDG_CACHE_HOME"
          "XDG_CONFIG_HOME"
          "XDG_DATA_DIRS"
          "XDG_DATA_HOME"
          "XDG_LOG_HOME"
          "XDG_STATE_HOME"
          "_JAVA_OPTIONS" ]
        |> List.map MakeCleanedEnvTuple

    let RunEbuildCommandsForEach
        (ebuildFiles: StringArray)
        (ebuildCommands: StringArray)
        (portageSettings: PortageSettings)
        (processSettings: ProcessSettings)
        : unit =
        let envMap =
            portageSettings.GetPortageEnv()
            @ EbuildCleanedEnvMap
            @ [ ("MAKEOPTS", $"-j {processSettings.Jobs} -l {processSettings.LoadAverage}") ]

        LogMessage Debug $"Enabled Portage FEATURES:    {portageSettings.GetFeatures}"
        LogMessage Debug $"Enabled Portage USE flags:   {portageSettings.GetUse}"
        LogMessage Debug $"Build process niceness:      {processSettings.Niceness}"
        LogMessage Debug $"Build process jobs:          {processSettings.Jobs}"
        LogMessage Debug $"Build process load average:  {processSettings.LoadAverage}"

        for ebuild in ebuildFiles do
            RunEbuildCommands ebuild ebuildCommands envMap processSettings.Niceness
