import Foundation import Logging import Models import MQTTNIO import NIO /// Sets up the application environment and connections required. /// /// - Parameters: /// - eventLoopGroup: The event loop group for the application. /// - logger: An optional logger for debugging. /// - autoConnect: A flag whether to auto-connect to the MQTT broker or not. // public func bootstrap( // eventLoopGroup: EventLoopGroup, // logger: Logger? = nil, // autoConnect: Bool = true // ) -> EventLoopFuture { // logger?.debug("Bootstrapping Dew Point Controller...") // // return loadEnvVars(eventLoopGroup: eventLoopGroup, logger: logger) // .and(loadTopics(eventLoopGroup: eventLoopGroup, logger: logger)) // .makeDewPointEnvironment(eventLoopGroup: eventLoopGroup, logger: logger) // .connectToMQTTBroker(autoConnect: autoConnect, logger: logger) // } // // /// Loads the ``EnvVars`` either using the defualts, from a file in the root directory under `.dewPoint-env` or in the shell / application environment. // /// // /// - Parameters: // /// - eventLoopGroup: The event loop group for the application. // /// - logger: An optional logger for debugging. // private func loadEnvVars( // eventLoopGroup: EventLoopGroup, // logger: Logger? // ) -> EventLoopFuture { // logger?.debug("Loading env vars...") // // // TODO: Need to have the env file path passed in / dynamic. // let envFilePath = URL(fileURLWithPath: #file) // .deletingLastPathComponent() // .deletingLastPathComponent() // .deletingLastPathComponent() // .appendingPathComponent(".dewPoint-env") // // let decoder = JSONDecoder() // let encoder = JSONEncoder() // // let defaultEnvVars = EnvVars() // // let defaultEnvDict = (try? encoder.encode(defaultEnvVars)) // .flatMap { try? decoder.decode([String: String].self, from: $0) } // ?? [:] // // // Read from file `.dewPoint-env` file if it exists. // let localEnvVarsDict = (try? Data(contentsOf: envFilePath)) // .flatMap { try? decoder.decode([String: String].self, from: $0) } // ?? [:] // // // Merge with variables in the shell environment. // let envVarsDict = defaultEnvDict // .merging(localEnvVarsDict, uniquingKeysWith: { $1 }) // .merging(ProcessInfo.processInfo.environment, uniquingKeysWith: { $1 }) // // // Produces the final env vars from the merged items or uses defaults if something // // went wrong. // let envVars = (try? JSONSerialization.data(withJSONObject: envVarsDict)) // .flatMap { try? decoder.decode(EnvVars.self, from: $0) } // ?? defaultEnvVars // // logger?.debug("Done loading env vars...") // return eventLoopGroup.next().makeSucceededFuture(envVars) // } // // // MARK: TODO perhaps make loading from file an option passed in when app is launched. // // /// Load the topics from file in application root directory at `.topics`, if available or fall back to the defualt. // /// // /// - Parameters: // /// - eventLoopGroup: The event loop group for the application. // /// - logger: An optional logger for debugging. // private func loadTopics(eventLoopGroup: EventLoopGroup, logger: Logger?) -> EventLoopFuture { // logger?.debug("Loading topics from file...") // // let topicsFilePath = URL(fileURLWithPath: #file) // .deletingLastPathComponent() // .deletingLastPathComponent() // .deletingLastPathComponent() // .appendingPathComponent(".topics") // // let decoder = JSONDecoder() // // // Attempt to load the topics from file in root directory. // let localTopics = (try? Data(contentsOf: topicsFilePath)) // .flatMap { try? decoder.decode(Topics.self, from: $0) } // // logger?.debug( // localTopics == nil // ? "Failed to load topics from file, falling back to defaults." // : "Done loading topics from file." // ) // // // If we were able to load from file use that, else fallback to the defaults. // return eventLoopGroup.next().makeSucceededFuture(localTopics ?? .init()) // } // // private extension EventLoopFuture where Value == (EnvVars, Topics) { // // /// Creates the ``DewPointEnvironment`` for the application after the ``EnvVars`` have been loaded. // /// // /// - Parameters: // /// - eventLoopGroup: The event loop group for the application. // /// - logger: An optional logger for the application. // func makeDewPointEnvironment( // eventLoopGroup: EventLoopGroup, // logger: Logger? // ) -> EventLoopFuture { // map { envVars, topics in // let mqttClient = MQTTClient(envVars: envVars, eventLoopGroup: eventLoopGroup, logger: logger) // return DewPointEnvironment( // envVars: envVars, // mqttClient: mqttClient, // topics: topics // ) // } // } // } // // private extension EventLoopFuture where Value == DewPointEnvironment { // // /// Connects to the MQTT broker after the ``DewPointEnvironment`` has been setup. // /// // /// - Parameters: // /// - logger: An optional logger for debugging. // func connectToMQTTBroker(autoConnect: Bool, logger: Logger?) -> EventLoopFuture { // guard autoConnect else { return self } // return flatMap { environment in // logger?.debug("Connecting to MQTT Broker...") // return environment.mqttClient.connect() // .map { _ in // logger?.debug("Successfully connected to MQTT Broker...") // return environment // } // } // } // } // // private extension MQTTNIO.MQTTClient { // // convenience init(envVars: EnvVars, eventLoopGroup: EventLoopGroup, logger: Logger?) { // self.init( // host: envVars.host, // port: envVars.port != nil ? Int(envVars.port!) : nil, // identifier: envVars.identifier, // eventLoopGroupProvider: .shared(eventLoopGroup), // logger: logger, // configuration: .init( // version: .v5_0, // userName: envVars.userName, // password: envVars.password // ) // ) // } // }