<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2017 <NAME>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Foundation
import Console
import Helpers
import JSON

public class Configuration: Command {
    public let id: String = "config"
    public let configPath = "/Library/Application Support/Ether/config.json"
    
    public let signature: [Argument] = [
       Value(name: "key", help: [
            "The configuration JSON key to set"
        ]),
       Value(name: "value", help: [
            "The new value for the key passed in"
        ])
    ]
    
    public let console: ConsoleProtocol
    
    public init(console: ConsoleProtocol) {
        self.console = console
    }
    
    public func run(arguments: [String]) throws {
        let setBar = console.loadingBar(title: "Setting Configuration Key")
        setBar.start()
        
        let fileManager = FileManager.default
        let key = try value("key", from: arguments)
        let val: String
        
        do {
            val = try value("value", from: arguments)
        } catch {
            if key == "help" { self.help() }
            return
        }
        
        guard let jsonPath = ConfigurationKey.getKey(from: key)?.jsonPath else {
            throw fail(bar: setBar, with: "Unable to get JSON path for specified key")
        }
        guard let configURL = URL(string: "file:\(fileManager.currentDirectoryPath)\(configPath)") else {
            throw fail(bar: setBar, with: "Unable to create path to config file")
        }
        
        let jsonData = try Data(contentsOf: configURL).makeBytes()
        var json = try JSON(bytes: jsonData)
        try self.set(jsonPath, with: val, in: &json)
        
        try Data(bytes: json.makeBytes()).write(to: configURL)
        
        setBar.finish()
    }
    
    fileprivate func help() {
        let help = """
        Below are the keys, values, and expected types for the configuration JSON.

        id |      key       | value-type |                       description
        ---+----------------+------------+-------------------------------------------------------------
         0 |     use-git    |    Bool    | Wheather to run git commands when a project is written to
         1 | install-commit |   String   | The message to use when committing after an installation
         2 |  remove-commit |   String   | The message to use when committing after a package removal
         3 |  latest-commit |   String   | The message to use when all packages are updated to their
           |                |            | latest versions
         4 |    new-commit  |   String   | The message to use when committing a newly generated project

        When a commit is made, there are variables that can be replaced for more specific messages.
        Below are the variables, their values, and the config ID that they belong to:

        id | var |    description
        ---+-----+--------------------
         1 | $0  | The package name
         1 | $1  | The package version
         2 | $0  | The package name
         4 | $0  | The project name<commit_msg>Added implementation for help property in Configuration class<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2017 <NAME>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Foundation
import Console
import Helpers
import JSON

public class Configuration: Command {
    public let id: String = "config"
    public let configPath = "/Library/Application Support/Ether/config.json"
    
    public let signature: [Argument] = [
       Value(name: "key", help: [
            "The configuration JSON key to set"
        ]),
       Value(name: "value", help: [
            "The new value for the key passed in"
        ])
    ]
    
    public let help: [String] = [
        "Configure custom actions to occure when a command is run",
        "Run `config help` to get information on expected data for the command options"
    ]
    
    public let console: ConsoleProtocol
    
    public init(console: ConsoleProtocol) {
        self.console = console
    }
    
    public func run(arguments: [String]) throws {
        let setBar = console.loadingBar(title: "Setting Configuration Key")
        setBar.start()
        
        let fileManager = FileManager.default
        let key = try value("key", from: arguments)
        let val: String
        
        do {
            val = try value("value", from: arguments)
        } catch {
            if key == "help" { printHelp() }
            return
        }
        
        guard let jsonPath = ConfigurationKey.getKey(from: key)?.jsonPath else {
            throw fail(bar: setBar, with: "Unable to get JSON path for specified key")
        }
        guard let configURL = URL(string: "file:\(fileManager.currentDirectoryPath)\(configPath)") else {
            throw fail(bar: setBar, with: "Unable to create path to config file")
        }
        
        let jsonData = try Data(contentsOf: configURL).makeBytes()
        var json = try JSON(bytes: jsonData)
        try self.set(jsonPath, with: val, in: &json)
        
        try Data(bytes: json.makeBytes()).write(to: configURL)
        
        setBar.finish()
    }
    
    fileprivate func printHelp() {
        let help = """
        Below are the keys, values, and expected types for the configuration JSON.

        id |      key       | value-type |                       description
        ---+----------------+------------+-------------------------------------------------------------
         0 |     use-git    |    Bool    | Wheather to run git commands when a project is written to
         1 | install-commit |   String   | The message to use when committing after an installation
         2 |  remove-commit |   String   | The message to use when committing after a package removal
         3 |  latest-commit |   String   | The message to use when all packages are updated to their
           |                |            | latest versions
         4 |    new-commit  |   String   | The message to use when committing a newly generated project

        When a commit is made, there are variables that can be replaced for more specific messages.
        Below are the variables, their values, and the config ID that they belong to:

        id | var |    description
        ---+-----+--------------------
         1 | $0  | The package name
         1 | $1  | The package version
         2 | $0  | The package name
         4 | $0  | The project name
{'fraction_non_alphanumeric': 0.10246856078248719, 'fraction_numerical': 0.0039590125756870055, 'mean_word_length': 2.034982332155477, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '343098', 'n_tokens_mistral': 2113, 'n_tokens_neox': 2052, 'n_words': 953}