/**
 * Log
 * ===
 *
 * @module log
 */

////////////////////////////////////////////////////////////////////////////////
// Imports
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Definitions
////////////////////////////////////////////////////////////////////////////////
/**
 *
 * @type {string}
 */
const DATE_FORMAT = 'YYYY-MM-DD HH:mm:ssZ';

/**
 *
 * @enum {int}
 */
const LOG_LEVEL = {
  ERROR: 0,
  WARN: 1,
  DEBUG: 2,
  INFO: 3,
  SILENT: 4
};

////////////////////////////////////////////////////////////////////////////////
// Class
////////////////////////////////////////////////////////////////////////////////
/**
 * Log
 * @class
 */
class Log {

  //////////////////////////////////////////////////////////////////////////////
  // Private Properties
  //////////////////////////////////////////////////////////////////////////////
  /**
   * @private
   * @type {number}
   */
  _level;

  /**
   * @private
   * @type {Array}
   */
  _data;

  //////////////////////////////////////////////////////////////////////////////
  // Public Properties
  //////////////////////////////////////////////////////////////////////////////

  /**
   * Log
   * @constructor
   * @param {number} level - The log level for the application.
   */
  constructor(level) {
    this._level = level;
    this._data = [];
  }

  ////////////////////////////////////////////////////////////////////////////////
  // Public Methods
  ////////////////////////////////////////////////////////////////////////////////
  /**
   * Writes a message to the log.
   * @public
   * @param {string} context - The name of the class logging the message.
   * @param {string} level - The level of the log message.
   * @param {object} message - The message to be written.
   */
  writeMessage(context, level, message) {
    if (LOG_LEVEL[level] <= this._level) return;
    let log = `[${level}][${Date.now()}][${context}]: `;

    if (typeof message === 'object') {
      log += `${JSON.stringify(message)}`;
    } else {
      log += `${message}`;
    }
    this._data.push(log);
    console.log(log);
  }

  /**
   * Clears the log.
   * @public
   */
  clear() {
    this._data = [];
  }

  ////////////////////////////////////////////////////////////////////////////////
  // Private Methods
  ////////////////////////////////////////////////////////////////////////////////
  /**
   * Static factory method
   * @static
   * @param {number} level - The minimum level for log messages.
   *
   * @return {Log} - A new log instance.
   */
  static createInstance(level) {
    return new Log(level);
  }
}

////////////////////////////////////////////////////////////////////////////////
// Exports
////////////////////////////////////////////////////////////////////////////////
export default Log;
