<commit_before>//
//  APIRouteHandler.swift
//  GitignoreIO
//
//  Created by <NAME> on 12/17/16.
//
//

import Foundation
import Vapor
import HTTP
import Lingo

//struct Encaps: Content {
//    var encapse = "encapse"
//    var sulation = "sulation"
//}
//
//struct Test: Content {
//    var hello = Encaps()
//}

internal class APIHandlers {
    private let splitSize = 5
    private var order: [String: Int]!
    private var templates: [String: IgnoreTemplateModel]!

    /// Initialze the API Handlers extension
    ///
    /// - Parameter templateController: All of the gitignore template objects
    init(templateController: TemplateController) {
        templates = templateController.templates
        order = templateController.order
    }

    /// Create the API endpoint for serving ignore templates
    ///
    /// - Parameter router: Vapor server side Swift router
    internal func createIgnoreEndpoint(router: Router) {
        router.get("/api", String.parameter) { request -> Response in
            let response = request.makeResponse()
            let ignoreString = try request.parameters.next(String.self)
            let (template, status) = self.createTemplate(ignoreString: ignoreString)
            try response.content.encode(template)
            response.http.status = status
            return response
        }
    }

    /// Create the API endpoint for downloading ignore templates
    ///
    /// - Parameter router: Vapor server side Swift router
    internal func createTemplateDownloadEndpoint(router: Router) {
        router.get("/api/f", String.parameter) { request -> HTTPResponse in
            let ignoreString = try request.parameters.next(String.self)
            let (template, status) = self.createTemplate(ignoreString: ignoreString)
            return HTTPResponse(status: status,
                         version: HTTPVersion(major: 1, minor: 0),
                         headers: HTTPHeaders([(HTTPHeaderName.contentDisposition.description, "attachment; filename=\"gitignore\"")]),
                         body: template)
        }
    }

    /// Create the API endpoint for showing the list of templates
    ///
    /// - Parameter router: Vapor server side Swift router
    internal func createListEndpoint(router: Router) {
        router.get("/api/list") { request -> Response in
            let response = request.makeResponse()

            let templateKeys =  self.templates.keys.sorted()
            guard let flags = try? request.query.decode(Flags.self),
                let format = flags.format else {
                let groupedLines =  stride(from: 0, to: templateKeys.count, by: self.splitSize)
                    .map {
                        templateKeys[$0..<min($0 + self.splitSize, templateKeys.count)].joined(separator: ",")
                    }
                    .joined(separator: "\n")
                try response.content.encode(groupedLines)
                return response
            }

            switch format {
            case "lines": try response.content.encode(templateKeys.joined(separator: "\n"))
            case "json": try response.content.encode(json: self.templates)
            default:
                try response.content.encode("Unknown Format: `lines` or `json` are acceptable formats")
                response.http.status = .internalServerError
            }
            return response
        }
    }

    /// Create the API endpoint for showing th eorder of templates
    ///
    /// - Parameter router: Vapor server side Swift router
    internal func createOrderEndpoint(router: Router) {
        router.get("/api/order") { request -> Response in
            let response = request.makeResponse()
            try response.content.encode(json: self.order)
            return response
        }
    }

    /// Create the API endpoint for help
    ///
    /// - Parameter router: Vapor server side Swift router
    internal func createHelp(router: Router) {
        router.get("/api/") { request in
            """
            gitignore.io help:
              list    - lists the operating systems, programming languages and IDE input types
              :types: - creates .gitignore files for types of operating systems, programming languages or IDEs
            """
        }
    }

    // MARK: - Private

    /// Create final output template sorted based on `data/order` file with headers
    /// and footers applied to templates
    ///
    /// - Parameter ignoreString: Comma separated string of templates to generate
    ///
    /// - Peturns: Final formatted template with headers and footers
    private func createTemplate(ignoreString: String) -> (template: String, status: HTTPResponseStatus) {
        guard let urlDecoded = ignoreString.removingPercentEncoding else {
            return ("\n#!! ERROR: url decoding \(ignoreString) !#\n", .internalServerError)
        }
        var createStatus: HTTPResponseStatus = .ok
        let template = urlDecoded
            .lowercased()
            .components(separatedBy: ",")
            .uniqueElements
            .sorted()
            .sorted(by: { (left: String, right: String) -> Bool in
                (self.order[left] ?? 0) < (self.order[right] ?? 0)
            })
            .map { (templateKey) -> String in
                guard let contents = self.templates[templateKey]?.contents else {
                    createStatus = .notFound
                    return "\n#!! ERROR: \(templateKey) is undefined. Use list command to see defined gitignore types !!#\n"
                }
                return contents
            }
            .reduce("\n# Created by https://www.gitignore.io/api/\(urlDecoded)\n") { (currentTemplate, contents) -> String in
                return currentTemplate.appending(contents)
            }
            .appending("\n\n# End of https://www.gitignore.io/api/\(urlDecoded)\n")
            .removeDuplicateLines()

        return (template: template, status: createStatus)<commit_msg>Add url for update template support<commit_after>//
//  APIRouteHandler.swift
//  GitignoreIO
//
//  Created by <NAME> on 12/17/16.
//
//

import Foundation
import Vapor
import HTTP
import Lingo

//struct Encaps: Content {
//    var encapse = "encapse"
//    var sulation = "sulation"
//}
//
//struct Test: Content {
//    var hello = Encaps()
//}

internal class APIHandlers {
    private let splitSize = 5
    private var order: [String: Int]!
    private var templates: [String: IgnoreTemplateModel]!

    /// Initialze the API Handlers extension
    ///
    /// - Parameter templateController: All of the gitignore template objects
    init(templateController: TemplateController) {
        templates = templateController.templates
        order = templateController.order
    }

    /// Create the API endpoint for serving ignore templates
    ///
    /// - Parameter router: Vapor server side Swift router
    internal func createIgnoreEndpoint(router: Router) {
        router.get("/api", String.parameter) { request -> Response in
            let response = request.makeResponse()
            let ignoreString = try request.parameters.next(String.self)
            let (template, status) = self.createTemplate(ignoreString: ignoreString)
            try response.content.encode(template)
            response.http.status = status
            return response
        }
    }

    /// Create the API endpoint for downloading ignore templates
    ///
    /// - Parameter router: Vapor server side Swift router
    internal func createTemplateDownloadEndpoint(router: Router) {
        router.get("/api/f", String.parameter) { request -> HTTPResponse in
            let ignoreString = try request.parameters.next(String.self)
            let (template, status) = self.createTemplate(ignoreString: ignoreString)
            return HTTPResponse(status: status,
                         version: HTTPVersion(major: 1, minor: 0),
                         headers: HTTPHeaders([(HTTPHeaderName.contentDisposition.description, "attachment; filename=\"gitignore\"")]),
                         body: template)
        }
    }

    /// Create the API endpoint for showing the list of templates
    ///
    /// - Parameter router: Vapor server side Swift router
    internal func createListEndpoint(router: Router) {
        router.get("/api/list") { request -> Response in
            let response = request.makeResponse()

            let templateKeys =  self.templates.keys.sorted()
            guard let flags = try? request.query.decode(Flags.self),
                let format = flags.format else {
                let groupedLines =  stride(from: 0, to: templateKeys.count, by: self.splitSize)
                    .map {
                        templateKeys[$0..<min($0 + self.splitSize, templateKeys.count)].joined(separator: ",")
                    }
                    .joined(separator: "\n")
                try response.content.encode(groupedLines)
                return response
            }

            switch format {
            case "lines": try response.content.encode(templateKeys.joined(separator: "\n"))
            case "json": try response.content.encode(json: self.templates)
            default:
                try response.content.encode("Unknown Format: `lines` or `json` are acceptable formats")
                response.http.status = .internalServerError
            }
            return response
        }
    }

    /// Create the API endpoint for showing th eorder of templates
    ///
    /// - Parameter router: Vapor server side Swift router
    internal func createOrderEndpoint(router: Router) {
        router.get("/api/order") { request -> Response in
            let response = request.makeResponse()
            try response.content.encode(json: self.order)
            return response
        }
    }

    /// Create the API endpoint for help
    ///
    /// - Parameter router: Vapor server side Swift router
    internal func createHelp(router: Router) {
        router.get("/api/") { _ in
            """
            gitignore.io help:
              list    - lists the operating systems, programming languages and IDE input types
              :types: - creates .gitignore files for types of operating systems, programming languages or IDEs
            """
        }
    }

    // MARK: - Private

    /// Create final output template sorted based on `data/order` file with headers
    /// and footers applied to templates
    ///
    /// - Parameter ignoreString: Comma separated string of templates to generate
    ///
    /// - Peturns: Final formatted template with headers and footers
    private func createTemplate(ignoreString: String) -> (template: String, status: HTTPResponseStatus) {
        guard let urlDecoded = ignoreString.removingPercentEncoding else {
            return ("""

                #!! ERROR: url decoding \(ignoreString) !#

                """, .internalServerError)
        }
        var createStatus: HTTPResponseStatus = .ok
        let template = urlDecoded
            .lowercased()
            .components(separatedBy: ",")
            .uniqueElements
            .sorted()
            .sorted(by: { (left: String, right: String) -> Bool in
                (self.order[left] ?? 0) < (self.order[right] ?? 0)
            })
            .map { (templateKey) -> String in
                guard let contents = self.templates[templateKey]?.contents else {
                    createStatus = .notFound
                    return """

                    #!! ERROR: \(templateKey) is undefined. Use list command to see defined gitignore types !!#

                    """
                }
                return contents
            }
            .reduce("""

                # Created by https://www.gitignore.io/api/\(urlDecoded)
                # Edit at https://www.gitignore.io/?templates=\(urlDecoded)

                """) { (currentTemplate, contents) -> String in
                return currentTemplate.appending(contents)
            }
            .appending("""

            # End of https://www.gitignore.io/api/\(urlDecoded)

            """)
            .removeDuplicateLines()

        return (template: template, status: createStatus)
{'fraction_non_alphanumeric': 0.10266688481675393, 'fraction_numerical': 0.0022905759162303663, 'mean_word_length': 1.9211469534050178, 'pattern_counts': {'":': 4, '<': 9, '<?xml version=': 0, '>': 21, 'https://': 5, 'lorem ipsum': 0, 'www.': 5, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6881112', 'n_tokens_mistral': 3054, 'n_tokens_neox': 2914, 'n_words': 892}