#!/usr/bin/env swift
/// Usage: $0 FOLDER
/// Description:
///   Merge all Swift files contained in FOLDER into swift code that can be used by the FolderSynchronizer.
/// Example: $0 Sources/SourceryRuntime > file.swift
/// Options:
///   FOLDERS: the paths where the Swift files to merge are, separated with comma ","
///   isForDarwinPlatform: if true, the generated code will be compilable on Darwin platforms
///   -h: Display this help message
import Foundation

func printUsage() {
    guard let scriptPath = CommandLine.arguments.first else {
        fatalError("Could not find script path in arguments (\(CommandLine.arguments))")
    }
    guard let lines = (try? String(contentsOfFile: scriptPath, encoding: .utf8))?
            .components(separatedBy: .newlines) else {
        fatalError("Could not read the script at path \(scriptPath)")
    }
    let documentationPrefix = "/// "
    lines
      .filter { $0.hasPrefix(documentationPrefix) }
      .map { $0.dropFirst(documentationPrefix.count) }
      .map { $0.replacingOccurrences(of: "$0", with: scriptPath) }
      .forEach { print("\($0)") }
}

extension String {
    func escapedSwiftTokens() -> String {
        // return self
        let replacements = [
          "\\(": "\\\\(",
          "\\\"": "\\\\\"",
          "\\n": "\\\\n",
        ]
        var escapedString = self
        replacements.forEach {
            escapedString = escapedString.replacingOccurrences(of: $0, with: $1)
        }
        return escapedString
    }
}

func package(folders folderPaths: [String], isForDarwinPlatform: Bool) throws {
    if !isForDarwinPlatform {
        print("#if !canImport(ObjectiveC)")
    } else {
        print("#if canImport(ObjectiveC)")
    }
    print("let sourceryRuntimeFiles: [FolderSynchronizer.File] = [")
    for folderPath in folderPaths {
        let folderURL = URL(fileURLWithPath: folderPath)

        guard let enumerator = FileManager.default.enumerator(at: folderURL, includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles, .skipsPackageDescendants]) else {
            print("Unable to retrieve file enumerator")
            exit(1)
        }
        var files = [URL]()
        for case let fileURL as URL in enumerator {
            do {
                let fileAttributes = try fileURL.resourceValues(forKeys:[.isRegularFileKey])
                if fileAttributes.isRegularFile! {
                    files.append(fileURL)
                }
            } catch { 
                print(error, fileURL) 
            }
        }
        
        try files
        .sorted(by: { $0.lastPathComponent < $1.lastPathComponent })
        .forEach { sourceFileURL in
            print("    .init(name: \"\(sourceFileURL.lastPathComponent)\", content:")
            print("\"\"\"")
            let content = try String(contentsOf: sourceFileURL, encoding: .utf8)
                .escapedSwiftTokens()
            print(content)
            print("\"\"\"),")
        }
    }
    print("]")
    print("#endif")
}

func main() {
    if CommandLine.arguments.contains("-h") {
        printUsage()
        exit(0)
    }
    guard CommandLine.arguments.count > 1 else {
        print("Missing folderPath argument")
        exit(1)
    }
    guard CommandLine.arguments.count > 2 else {
        print("Missing isForDarwinPlatform argument")
        exit(1)
    }
    let foldersPaths = CommandLine.arguments[1]
    let isForDarwinPlatform = Bool(CommandLine.arguments[2]) ?? false
    let folders = foldersPaths.split(separator: ",").map(String.init)

    do {
        try package(folders: folders, isForDarwinPlatform: isForDarwinPlatform)
    } catch {
        print("Failed with error: \(error)")
        exit(1)
    }
}

main()
