import Foundation

struct Configuration {

    let serverPort: Int

    let mail: EMail?

    struct EMail {

        /// The url to the root of the server
        let serverDomain: String

        /// SMTP server address
        let emailHostname: String

        /// username to login
        let email: String

        /// password to login
        let password: String

        /// The number of minutes until a password reset token is no longer valid
        let tokenExpiryDuration: Int
    }
    
    /**
     The folder where the data should be stored.
     
     If the folder is set to `nil`, then the `Resources` folder is used.
     */
    let dataDirectory: String?

    /// The authentication tokens to access the metrics
    let monitoringTokens: Set<String>
    
    /// The path to the folder where the metric logs are stored
    ///
    /// If no path is provided, then a folder `logs` in the resources directory is created
    /// If the path is relative, then it is assumed relative to the resources directory
    let logPath: String?
    
    func logURL(possiblyRelativeTo resourcesDirectory: URL) -> URL {
        guard let logPath else {
            return resourcesDirectory.appendingPathComponent("logs")
        }
        guard !logPath.hasPrefix("/") else {
            return .init(fileURLWithPath: logPath)
        }
        return resourcesDirectory.appendingPathComponent(logPath)
    }
    
    func customDataDirectory(or publicDirectory: String) -> URL {
        guard let dataDirectory else {
            return URL(fileURLWithPath: publicDirectory)
        }
        return URL(fileURLWithPath: dataDirectory)
    }
}

extension Configuration {

    init(loadFromUrl url: URL) throws {
        let data: Data
        do {
            data = try Data(contentsOf: url)
        } catch {
            log("Failed to load configuration data from \(url.path): \(error)")
            throw error
        }
        try self.init(data: data)
    }

    init(data: Data) throws {
        do {
            self = try JSONDecoder().decode(Configuration.self, from: data)
        } catch {
            log("Failed to decode configuration: \(error)")
            throw error
        }
    }
}

extension Configuration.EMail: Codable {
    
}

extension Configuration: Codable {

}
