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

namespace Gdmt.License

module Private =
    open System
    open System.Diagnostics
    open System.IO
    open System.Text.RegularExpressions

    open FSharp.Data

    type NugetLicenseProvider =
        JsonProvider<"""
            [
                {
                    "PackageId": "PackageId",
                    "PackageVersion": "PackageVersion",
                    "PackageProjectUrl": "PackageProjectUrl",
                    "License": "License",
                    "LicenseInformationOrigin": 0
                }
            ]
        """>

    let FindValidProjectFile (path: string) : string =
        match path with
        | f when File.Exists f -> f
        | d when Directory.Exists d ->
            let triedSlnFiles = Directory.GetFiles(path, "*.sln") |> Array.sort
            let triedProjFiles = Directory.GetFiles(path, "*proj") |> Array.sort

            if triedSlnFiles.Length > 0 then
                triedSlnFiles[0]
            elif triedProjFiles.Length > 0 then
                triedProjFiles[0]
            else
                "no sln/proj files found in specified directory" |> Exception |> raise
        | p -> $"no such file or directory, given {p}" |> Exception |> raise

    let ExecuteNugetLicense (path: string) : string =
        let projectFile = FindValidProjectFile path
        let nugetLicenseCommand = $"nuget-license -t -o Json -i {projectFile}"

        let processStartInfo =
            new ProcessStartInfo("/bin/sh", $"-c \"{nugetLicenseCommand}\"")

        processStartInfo.RedirectStandardOutput <- true
        processStartInfo.UseShellExecute <- false
        processStartInfo.CreateNoWindow <- true

        use startedProcess = new Process()
        startedProcess.StartInfo <- processStartInfo
        startedProcess.Start() |> ignore

        let output = startedProcess.StandardOutput.ReadToEnd()
        startedProcess.WaitForExit()

        output

    // Probably safe to skip licenses.
    let IgnoredLicenses = [| "MS-EULA"; "MS-PL" |]

    let IsIgnoredLicense (license: string) : bool =
        IgnoredLicenses |> Array.contains license

    let IsAcceptedLicense (license: string) : bool =
        match license with
        | empty when String.IsNullOrEmpty empty -> false
        | url when Regex.IsMatch(url, "http.*//.+") -> false
        | ignored when IsIgnoredLicense ignored -> false
        | _ -> true
