<commit_before>#load "Helpers.fsx"
#load "SwaggerInjector.fsx"

open Helpers
open SwaggerInjector
open System
open System.Diagnostics
open System.IO
open System.Linq
open System.Text
open System.Text.RegularExpressions

let work tempDir fsDir = 
    tempDir
    |> loopFiles
    |> Seq.iter (fun f -> File.Copy(f, fsDir <!!> Path.GetFileName(f)))

module CSharp =
    let private generateSwaggerModel() = 
        !>> "Cleaning Models, Api & Client directories"
        [modelsTempDir; modelsDir; apiDir; clientDir] |> Seq.iter (ensureDir >> ignore)
        [modelsTempDir; modelsDir; apiDir; clientDir] |> Seq.iter emptyDir
        javaExec <| sprintf """-jar %s generate -i %s -l csharp -t %s -o obj -c %s""" (toolsDir <!!> "swagger-codegen-cli.jar") (specDir <!!> "swagger-full.json") (specDir <!!> "cs-template") (scriptDir <!!> "codegen-config.json")
        let generatedFiles = Directory.GetFiles(modelsTempDir).Count()
        if generatedFiles > 0 then
            brk()
            !> (sprintf "%i files generated." generatedFiles)
            brk()
        else
            brk()
            !> "Swagger code generation failed." 
            brk()

    let private cleanup() = 
        /// Perform specific code cleanups
        let codeCorrection (fileName : string) (l : string) =
            // Correct constructors
            let mutable line = l.Replace(", )", ")")
            // Remove all null-able types
            line <- line.Replace("?", "")
            // Correct enums
            if line.Contains(".\"") then 
                let startPos = line.IndexOf(".\"")
                let endPos = line.LastIndexOf("\"")
                line <- line.Remove(startPos + 1, 1)
                line <- line.Remove(endPos - 1, 1)
            // Convert lists to array
            if line.Contains("List<") then
                line <- line.Replace("List<", "")
                line <- line.Replace(">>", "%%")
                line <- line.Replace(">", "[]")
                line <- line.Replace("%%", ">")
            // Covers the corner case when we have arrays of basic data type
            line <- line.Replace("= new string[]();", "= Array.Empty<string>();")
            // Specify the format type for ToString for date time field
            if line.EndsWith("//datetime") then
                line <- line.Replace(".ToString()", """.ToString("yyyyMMddHHmmss")""")
            // Change Dictionary<string,string> to List<KeyValuePair<string, string>>
            if fileName.Contains("OperationMessage.cs") then
                line <- line.Replace("Dictionary<string, string>", "List<KeyValuePair<string, string>>")
        
            line

        let deleteProperty propName fileStr =
            Regex.Replace(fileStr, 
                          sprintf @"\/\/\/[\s]*<summary>[^<]+<\/[^<]*%s[\s]*{[\s]*get;[^/]+" propName, 
                          "")

        let perFileCleanup (fileName : string) (contents : string) =
            // Delete properties from extended classes
            if contents.Contains(": FlexResponse") then
                ["Error"; "ErrorDescription"; "ErrorField"]
                |> Seq.fold (fun acc value -> acc |> deleteProperty value) contents
            else contents

        let cleanupFile(f : string) =
            let mutable file = File.ReadAllLines(f)
            let fileSb = new StringBuilder()
            file 
            |> Array.map (codeCorrection f)
            |> Array.filter (String.IsNullOrWhiteSpace >> not)
            |> Array.iter (fileSb.AppendLine >> ignore)

            fileSb.ToString()
            |> perFileCleanup f
            |> fun fileContents -> File.WriteAllText(f, fileContents)
        
        modelsTempDir
        |> loopFiles
        |> Seq.iter cleanupFile
    
    let private formatCode() =
        exec(codeFormatterExe, sprintf "%s/FlexSearch.Api/FlexSearch.Api.csproj /nocopyright" srcDir)
    
    let private copy() =
        work modelsTempDir modelsDir
        work apiTempDir apiDir 
        work clientTempDir clientDir 
    
    let generateCSharp() =
        brk()
        !> "Generating CSharp API models"
        generateSwaggerModel()
        !>> "Cleaning up the generated files"
        cleanup()<commit_msg>fix(api) : Responses don't need to inherit from IDataTransferObject<commit_after>#load "Helpers.fsx"
#load "SwaggerInjector.fsx"

open Helpers
open SwaggerInjector
open System
open System.Diagnostics
open System.IO
open System.Linq
open System.Text
open System.Text.RegularExpressions

let work tempDir fsDir = 
    tempDir
    |> loopFiles
    |> Seq.iter (fun f -> File.Copy(f, fsDir <!!> Path.GetFileName(f)))

module CSharp =
    let private generateSwaggerModel() = 
        !>> "Cleaning Models, Api & Client directories"
        [modelsTempDir; modelsDir; apiDir; clientDir] |> Seq.iter (ensureDir >> ignore)
        [modelsTempDir; modelsDir; apiDir; clientDir] |> Seq.iter emptyDir
        javaExec <| sprintf """-jar %s generate -i %s -l csharp -t %s -o obj -c %s""" (toolsDir <!!> "swagger-codegen-cli.jar") (specDir <!!> "swagger-full.json") (specDir <!!> "cs-template") (scriptDir <!!> "codegen-config.json")
        let generatedFiles = Directory.GetFiles(modelsTempDir).Count()
        if generatedFiles > 0 then
            brk()
            !> (sprintf "%i files generated." generatedFiles)
            brk()
        else
            brk()
            !> "Swagger code generation failed." 
            brk()

    let private cleanup() = 
        /// Perform specific code cleanups
        let codeCorrection (fileName : string) (l : string) =
            // Correct constructors
            let mutable line = l.Replace(", )", ")")
            // Remove all null-able types
            line <- line.Replace("?", "")
            // Correct enums
            if line.Contains(".\"") then 
                let startPos = line.IndexOf(".\"")
                let endPos = line.LastIndexOf("\"")
                line <- line.Remove(startPos + 1, 1)
                line <- line.Remove(endPos - 1, 1)
            // Convert lists to array
            if line.Contains("List<") then
                line <- line.Replace("List<", "")
                line <- line.Replace(">>", "%%")
                line <- line.Replace(">", "[]")
                line <- line.Replace("%%", ">")
            // Covers the corner case when we have arrays of basic data type
            line <- line.Replace("= new string[]();", "= Array.Empty<string>();")
            // Specify the format type for ToString for date time field
            if line.EndsWith("//datetime") then
                line <- line.Replace(".ToString()", """.ToString("yyyyMMddHHmmss")""")
            // Change Dictionary<string,string> to List<KeyValuePair<string, string>>
            if fileName.Contains("OperationMessage.cs") then
                line <- line.Replace("Dictionary<string, string>", "List<KeyValuePair<string, string>>")
        
            line

        let tag name = sprintf @"[\s]*<%s>[^<]+<\/%s>" name name

        let deleteProperty fileStr propName  =
            Regex.Replace(fileStr, 
                          sprintf @"\/\/\/[\s]*<summary>[^<]+<\/[^<]*%s[\s]*{[\s]*get;[^/]+" propName, 
                          "")

        let deleteMethod fileStr methName  =
            Regex.Replace(fileStr, 
                          sprintf @"\/\/\/%s[^<]*%s[^<]*%s\(\)[\s]*{[^/]+" (tag "summary") (tag "returns") methName, 
                          "")

        let perFileCleanup (fileName : string) (contents : string) =
            // Delete properties from extended FlexResponse class
            if contents.Contains(": FlexResponse") then
                ["Error"; "ErrorDescription"; "ErrorField"]
                |> Seq.fold deleteProperty contents
            else contents
            // Response classes shouldn't implement IDataTransferObject
            |> fun contents' -> 
                if fileName.EndsWith("Response.cs") then
                    ["Validated"; "ErrorDescription"; "ErrorField"]
                    |> Seq.fold deleteProperty contents'
                    |> fun contents'' -> Regex.Replace(contents'', "IDataTransferObject,[\s]", "")
                    |> fun contents'' -> deleteMethod contents'' "Validate"
                else contents'

        let cleanupFile(f : string) =
            let mutable file = File.ReadAllLines(f)
            let fileSb = new StringBuilder()
            file 
            |> Array.map (codeCorrection f)
            |> Array.filter (String.IsNullOrWhiteSpace >> not)
            |> Array.iter (fileSb.AppendLine >> ignore)

            fileSb.ToString()
            |> perFileCleanup f
            |> fun fileContents -> File.WriteAllText(f, fileContents)
        
        modelsTempDir
        |> loopFiles
        |> Seq.iter cleanupFile
    
    let private formatCode() =
        exec(codeFormatterExe, sprintf "%s/FlexSearch.Api/FlexSearch.Api.csproj /nocopyright" srcDir)
    
    let private copy() =
        work modelsTempDir modelsDir
        work apiTempDir apiDir 
        work clientTempDir clientDir 
    
    let generateCSharp() =
        brk()
        !> "Generating CSharp API models"
        generateSwaggerModel()
        !>> "Cleaning up the generated files"
        cleanup()
{'fraction_non_alphanumeric': 0.1343733189887036, 'fraction_numerical': 0.0010758472296933835, 'mean_word_length': 1.9168497019140258, 'pattern_counts': {'":': 2, '<': 66, '<?xml version=': 0, '>': 104, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1169758', 'n_tokens_mistral': 2632, 'n_tokens_neox': 2505, 'n_words': 662}