// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:core';
import 'dart:io';

/// Determines the level of logging.
///
/// Verbosity is increasing from one (none) to five (fine). The sixth level
/// (all) logs everything.
enum LoggingLevel {
  /// Logs no logs.
  none,

  /// Logs severe messages at the most (severe messages are always logged).
  ///
  /// Severe means that the process has encountered a critical level of failure
  /// in which it cannot recover and will terminate as a result.
  severe,

  /// Logs warning messages at the most.
  ///
  /// Warning implies that an error was encountered, but the process will
  /// attempt to continue, and may/may not succeed.
  warning,

  /// Logs info messages at the most.
  ///
  /// An info message is for determining information about the state of the
  /// application as it runs through execution.
  info,

  /// Logs fine logs at the most.
  ///
  /// A fine message is one that is not important for logging outside of
  /// debugging potential issues in the application.
  fine,

  /// Logs everything.
  all,
}

/// Signature of a function that logs a [LogMessage].
typedef LoggingFunction = void Function(LogMessage log);

/// The default logging function.
///
/// Runs the [print] function using the format string:
///   '[${log.levelName}]::${log.tag}--${log.time}: ${log.message}'
///
/// Exits with status code 1 if the `log` is [LoggingLevel.severe].
void defaultLoggingFunction(LogMessage log) {
  // ignore: avoid_print
  print('[${log.levelName}]::${log.tag}--${log.time}: ${log.message}');
  if (log.level == LoggingLevel.severe) {
    exit(1);
  }
}

/// Represents a logging message created by the logger.
///
/// Includes a message, the time the message was created, the level of the log
/// as an enum, the name of the level as a string, and a tag. This class is used
/// to print from the global logging function defined in
/// [Logger.loggingFunction] (a function that can be user-defined).
class LogMessage {
  /// Creates a log, including the level of the log, the time it was created,
  /// and the actual log message.
  ///
  /// When this message is created, it sets its [time] to [DateTime.now].
  LogMessage(this.message, this.tag, this.level)
    : levelName = level.toString().substring(level.toString().indexOf('.') + 1),
      time = DateTime.now();

  /// The actual log message.
  final String message;

  /// The time the log message was created.
  final DateTime time;

  /// The level of this log.
  final LoggingLevel level;

  /// The human readable level of this log.
  final String levelName;

  /// The tag associated with the message. This is set to [Logger.tag] when
  /// emitted by a [Logger] object.
  final String tag;
}

/// Logs messages using the global [LoggingFunction] and logging level.
///
/// Example of setting log level to [LoggingLevel.warning] and creating a
/// logging function:
///
/// ```dart
/// Logger.globalLevel = LoggingLevel.warning;
/// ```
class Logger {
  /// Creates a logger with the given [tag].
  Logger(this.tag);

  /// The tag associated with the log message (usable in the logging function).
  /// [LogMessage] objects emitted by this class will have [LogMessage.tag] set
  /// to this value.
  final String tag;

  /// Determines what to do when the [Logger] creates and attempts to log a
  /// [LogMessage] object.
  ///
  /// This function can be reassigned to whatever functionality of your
  /// choosing, so long as it has the same signature of [LoggingFunction] (it
  /// can also be an asynchronous function, if doing file I/O, for
  /// example).
  static LoggingFunction loggingFunction = defaultLoggingFunction;

  /// Determines the logging level all [Logger] instances use.
  static LoggingLevel globalLevel = LoggingLevel.none;

  /// Logs a [LoggingLevel.severe] level `message`.
  ///
  /// Severe messages are always logged, regardless of what level is set.
  void severe(String message) {
    loggingFunction(LogMessage(message, tag, LoggingLevel.severe));
  }

  /// Logs a [LoggingLevel.warning] level `message`.
  void warning(String message) {
    if (globalLevel.index >= LoggingLevel.warning.index) {
      loggingFunction(LogMessage(message, tag, LoggingLevel.warning));
    }
  }

  /// Logs a [LoggingLevel.info] level `message`.
  void info(String message) {
    if (globalLevel.index >= LoggingLevel.info.index) {
      loggingFunction(LogMessage(message, tag, LoggingLevel.info));
    }
  }

  /// Logs a [LoggingLevel.fine] level `message`.
  void fine(String message) {
    if (globalLevel.index >= LoggingLevel.fine.index) {
      loggingFunction(LogMessage(message, tag, LoggingLevel.fine));
    }
  }
}
