/*
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file
 distributed with this work for additional information
 regarding copyright ownership.  The ASF licenses this file
 to you under the Apache License, Version 2.0 (the
 "License"); you may not use this file except in compliance
 with the License.  You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing,
 software distributed under the License is distributed on an
 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 */

const ansi = require('ansi');
const EventEmitter = require('events').EventEmitter;
const EOL = require('os').EOL;
const formatError = require('./util/formatError');

const INSTANCE_KEY = Symbol.for('org.apache.cordova.common.CordovaLogger');

/**
 * @typedef {'verbose'|'normal'|'warn'|'info'|'error'|'results'} CordovaLoggerLevel
 */

/**
 * Implements logging facility that anybody could use.
 *
 * Should not be instantiated directly! `CordovaLogger.get()` method should be
 * used instead to acquire the logger instance.
 */
class CordovaLogger {
    // Encapsulate the default logging level values with constants:
    static get VERBOSE () { return 'verbose'; }

    static get NORMAL () { return 'normal'; }

    static get WARN () { return 'warn'; }

    static get INFO () { return 'info'; }

    static get ERROR () { return 'error'; }

    static get RESULTS () { return 'results'; }

    /**
     * Static method to create new or acquire existing instance.
     *
     * @returns {CordovaLogger} Logger instance
     */
    static get () {
        // This singleton instance pattern is based on the ideas from
        // https://derickbailey.com/2016/03/09/creating-a-true-singleton-in-node-js-with-es6-symbols/
        if (Object.getOwnPropertySymbols(global).indexOf(INSTANCE_KEY) === -1) {
            global[INSTANCE_KEY] = new CordovaLogger();
        }
        return global[INSTANCE_KEY];
    }

    constructor () {
        /** @private */
        this.levels = {};
        /** @private */
        this.colors = {};
        /** @private */
        this.stdout = process.stdout;
        /** @private */
        this.stderr = process.stderr;

        /** @private */
        this.stdoutCursor = ansi(this.stdout);
        /** @private */
        this.stderrCursor = ansi(this.stderr);

        this.addLevel(CordovaLogger.VERBOSE, 1000, 'grey');
        this.addLevel(CordovaLogger.NORMAL, 2000);
        this.addLevel(CordovaLogger.WARN, 2000, 'yellow');
        this.addLevel(CordovaLogger.INFO, 3000, 'blue');
        this.addLevel(CordovaLogger.ERROR, 5000, 'red');
        this.addLevel(CordovaLogger.RESULTS, 10000);

        this.setLevel(CordovaLogger.NORMAL);
    }

    /**
     * Emits log message to process' stdout/stderr depending on message's
     * severity and current log level. If severity is less than current
     * logger's level, then the message is ignored.
     *
     * @param {CordovaLoggerLevel} logLevel - The message's log level. The
     *   logger should have corresponding level added (via logger.addLevel),
     *   otherwise `CordovaLogger.NORMAL` level will be used.
     *
     * @param {string} message - The message, that should be logged to
     *   process's stdio.
     *
     * @returns {CordovaLogger} Return the current instance, to allow chaining.
     */
    log (logLevel, message) {
        // if there is no such logLevel defined, or provided level has
        // less severity than active level, then just ignore this call and return
        if (!this.levels[logLevel] || this.levels[logLevel] < this.levels[this.logLevel]) {
            // return instance to allow to chain calls
            return this;
        }

        const isVerbose = this.logLevel === CordovaLogger.VERBOSE;
        let cursor = this.stdoutCursor;

        if (message instanceof Error || logLevel === CordovaLogger.ERROR) {
            message = formatError(message, isVerbose);
            cursor = this.stderrCursor;
        }

        const color = this.colors[logLevel];
        if (color) {
            cursor.bold().fg[color]();
        }

        cursor.write(message).reset().write(EOL);

        return this;
    }

    /**
     * Adds a new level to logger instance.
     *
     * This method also creates a shortcut method to log events with the level
     * provided.
     * (i.e. after adding new level 'debug', the method `logger.debug(message)`
     * will exist, equal to `logger.log('debug', message)`)
     *
     * @param {CordovaLoggerLevel} level - A log level name. The levels with
     *   the following names are added by default to every instance: 'verbose',
     *   'normal', 'warn', 'info', 'error', 'results'.
     *
     * @param {number} severity - A number that represents level's severity.
     *
     * @param {string} color - A valid color name, that will be used to log
     *   messages with this level. Any CSS color code or RGB value is allowed
     *   (according to ansi documentation:
     *   https://github.com/TooTallNate/ansi.js#features).
     *
     * @returns {CordovaLogger} Return the current instance, to allow chaining.
     */
    addLevel (level, severity, color) {
        this.levels[level] = severity;

        if (color) {
            this.colors[level] = color;
        }

        // Define own method with corresponding name
        if (!this[level]) {
            Object.defineProperty(this, level, {
                get () { return this.log.bind(this, level); }
            });
        }

        return this;
    }

    /**
     * Sets the current logger level to provided value.
     *
     * If logger doesn't have level with this name, `CordovaLogger.NORMAL` will
     * be used.
     *
     * @param {CordovaLoggerLevel} logLevel - Level name. The level with this
     *   name should be added to logger before.
     *
     * @returns {CordovaLogger} Current instance, to allow chaining.
     */
    setLevel (logLevel) {
        this.logLevel = this.levels[logLevel] ? logLevel : CordovaLogger.NORMAL;

        return this;
    }

    /**
     * Adjusts the current logger level according to the passed options.
     *
     * @param {Object|Array<string>} opts - An object or args array with
     *   options.
     *
     * @returns {CordovaLogger} Current instance, to allow chaining.
     */
    adjustLevel (opts) {
        if (opts.verbose || (Array.isArray(opts) && opts.includes('--verbose'))) {
            this.setLevel('verbose');
        } else if (opts.silent || (Array.isArray(opts) && opts.includes('--silent'))) {
            this.setLevel('error');
        }

        return this;
    }

    /**
     * Attaches logger to EventEmitter instance provided.
     *
     * @param {EventEmitter} eventEmitter - An EventEmitter instance to attach
     *   the logger to.
     *
     * @returns {CordovaLogger} Current instance, to allow chaining.
     */
    subscribe (eventEmitter) {
        if (!(eventEmitter instanceof EventEmitter)) {
            throw new Error('Subscribe method only accepts an EventEmitter instance as argument');
        }

        eventEmitter.on('verbose', this.verbose)
            .on('log', this.normal)
            .on('info', this.info)
            .on('warn', this.warn)
            .on('warning', this.warn)
            // Set up event handlers for logging and results emitted as events.
            .on('results', this.results);

        return this;
    }
}

module.exports = CordovaLogger;
