//
//  Logger.swift
//  BadgeLog
//
//  Created by Daniele Bachicchi on 28/01/22.
//

import Foundation


/// Handle all logs logic
///
/// Before using it, remember to call 'Logger.setup' to initialize it. Just call once,
/// preferably on application startup.
///
/// - author: Daniele Bachicchi
///
public final class Logger {
    public enum LogLevel: Int {
        case verbose
        case debug
        case info
        case warning
        case error
        }
    
    /// Singleton instance of Logger class
    public static let shared: Logger = Logger()
    
    /// Flag to enable/disable generate log into file.
    public var enableFileLogging = true
    /// Flag to enable/disable generate log into console.
    public var enableConsoleLogging = true
    /// Min level of log. Log with level under this will not be printed.
    public var minLevel: LogLevel = .verbose
    
    private var destinations: [LogInterpreter] = []
    
    
    /// Initialize Logger functionality.
    /// set 'enableFileLogging', 'enableConsoleLogging', 'minLevel' before call 'setup()'
    public func setup(destinations: [LogInterpreter] = [ConsoleDestination()]){
        self.destinations = destinations
        
    }
    
    /**
             Retrieve all existing log file generated by all `FileDestination` added during `Logger.setup()`
             
             - Returns: all log files generated.
    */
    public func getLogFiles() -> [LogFile] {
        var result: [LogFile] = []
        for destination in destinations {
            if destination is FileDestination {
                let fileDestination = destination as! FileDestination
                result.append(contentsOf: fileDestination.getLogFiles())
            }
        }
        return result
        
    }
    
}


extension Logger: Logging {
    public func info(_ message: String, error: NSError? = nil, file:String = #file, function: String = #function, line: Int = #line) {
        log(.info, message, error: error, file: file, function: function, line: line)
    }
    
    public func debug(_ message: String, error: NSError? = nil, file:String = #file, function: String = #function, line: Int = #line) {
        log(.debug, message, error: error, file: file, function: function, line: line)
    }
    public func warning(_ message: String, error: NSError? = nil, file:String = #file, function: String = #function, line: Int = #line) {
        log(.warning, message, error: error, file: file, function: function, line: line)
    }
    public func verbose(_ message: String, error: NSError? = nil, file:String = #file, function: String = #function, line: Int = #line) {
        log(.verbose, message, error: error, file: file, function: function, line: line)
    }
    public func error(_ message: String, error: NSError? = nil, file:String = #file, function: String = #function, line: Int = #line) {
        log(.error, message, error: error, file: file, function: function, line: line)
    }
    
    internal func log(_ level: LogLevel, _ message: String, error: NSError?, file: String = #file, function: String = #function, line: Int = #line) {
         
        for destination in destinations {
            let _ = destination.send(level: level, msg: message, error: error, file: file, function: function, line: line)
            
        }
     }
}
