/**
 * @fileoverview An object that caches and applies source code fixes.
 * @author Nicholas C. Zakas
 */
"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const debug = require("debug")("eslint:text-fixer");

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------

const BOM = "\uFEFF";

/**
 * Compares items in a messages array by range.
 * @param {Message} a The first message.
 * @param {Message} b The second message.
 * @returns {int} -1 if a comes before b, 1 if a comes after b, 0 if equal.
 * @private
 */
function compareMessagesByFixRange(a, b) {
    return a.fix.range[0] - b.fix.range[0] || a.fix.range[1] - b.fix.range[1];
}

/**
 * Compares items in a messages array by line and column.
 * @param {Message} a The first message.
 * @param {Message} b The second message.
 * @returns {int} -1 if a comes before b, 1 if a comes after b, 0 if equal.
 * @private
 */
function compareMessagesByLocation(a, b) {
    return a.line - b.line || a.column - b.column;
}

//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------

/**
 * Utility for apply fixes to source code.
 * @constructor
 */
function SourceCodeFixer() {
    Object.freeze(this);
}

/**
 * Applies the fixes specified by the messages to the given text. Tries to be
 * smart about the fixes and won't apply fixes over the same area in the text.
 * @param {string} sourceText The text to apply the changes to.
 * @param {Message[]} messages The array of messages reported by ESLint.
 * @param {boolean|Function} [shouldFix=true] Determines whether each message should be fixed
 * @returns {Object} An object containing the fixed text and any unfixed messages.
 */
SourceCodeFixer.applyFixes = function(sourceText, messages, shouldFix) {
    debug("Applying fixes");

    if (shouldFix === false) {
        debug("shouldFix parameter was false, not attempting fixes");
        return {
            fixed: false,
            messages,
            output: sourceText
        };
    }

    // clone the array
    const remainingMessages = [],
        fixes = [],
        bom = sourceText.startsWith(BOM) ? BOM : "",
        text = bom ? sourceText.slice(1) : sourceText;
    let lastPos = Number.NEGATIVE_INFINITY,
        output = bom;

    /**
     * Try to use the 'fix' from a problem.
     * @param   {Message} problem The message object to apply fixes from
     * @returns {boolean}         Whether fix was successfully applied
     */
    function attemptFix(problem) {
        const fix = problem.fix;
        const start = fix.range[0];
        const end = fix.range[1];

        // Remain it as a problem if it's overlapped or it's a negative range
        if (lastPos >= start || start > end) {
            remainingMessages.push(problem);
            return false;
        }

        // Remove BOM.
        if ((start < 0 && end >= 0) || (start === 0 && fix.text.startsWith(BOM))) {
            output = "";
        }

        // Make output to this fix.
        output += text.slice(Math.max(0, lastPos), Math.max(0, start));
        output += fix.text;
        lastPos = end;
        return true;
    }

    messages.forEach(problem => {
        if (problem.hasOwnProperty("fix")) {
            fixes.push(problem);
        } else {
            remainingMessages.push(problem);
        }
    });

    if (fixes.length) {
        debug("Found fixes to apply");
        let fixesWereApplied = false;

        for (const problem of fixes.sort(compareMessagesByFixRange)) {
            if (typeof shouldFix !== "function" || shouldFix(problem)) {
                attemptFix(problem);

                /*
                 * The only time attemptFix will fail is if a previous fix was
                 * applied which conflicts with it.  So we can mark this as true.
                 */
                fixesWereApplied = true;
            } else {
                remainingMessages.push(problem);
            }
        }
        output += text.slice(Math.max(0, lastPos));

        return {
            fixed: fixesWereApplied,
            messages: remainingMessages.sort(compareMessagesByLocation),
            output
        };
    }

    debug("No fixes to apply");
    return {
        fixed: false,
        messages,
        output: bom + text
    };

};

module.exports = SourceCodeFixer;
