/**
 * @fileoverview Rule to disallow use of unmodified expressions in loop conditions
 * @author Toru Nagashima
 */

"use strict";

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

const Traverser = require("../util/traverser"),
    astUtils = require("../ast-utils");

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

const pushAll = Function.apply.bind(Array.prototype.push);
const SENTINEL_PATTERN = /(?:(?:Call|Class|Function|Member|New|Yield)Expression|Statement|Declaration)$/;
const LOOP_PATTERN = /^(?:DoWhile|For|While)Statement$/; // for-in/of statements don't have `test` property.
const GROUP_PATTERN = /^(?:BinaryExpression|ConditionalExpression)$/;
const SKIP_PATTERN = /^(?:ArrowFunction|Class|Function)Expression$/;
const DYNAMIC_PATTERN = /^(?:Call|Member|New|TaggedTemplate|Yield)Expression$/;

/**
 * @typedef {Object} LoopConditionInfo
 * @property {eslint-scope.Reference} reference - The reference.
 * @property {ASTNode} group - BinaryExpression or ConditionalExpression nodes
 *      that the reference is belonging to.
 * @property {Function} isInLoop - The predicate which checks a given reference
 *      is in this loop.
 * @property {boolean} modified - The flag that the reference is modified in
 *      this loop.
 */

/**
 * Checks whether or not a given reference is a write reference.
 *
 * @param {eslint-scope.Reference} reference - A reference to check.
 * @returns {boolean} `true` if the reference is a write reference.
 */
function isWriteReference(reference) {
    if (reference.init) {
        const def = reference.resolved && reference.resolved.defs[0];

        if (!def || def.type !== "Variable" || def.parent.kind !== "var") {
            return false;
        }
    }
    return reference.isWrite();
}

/**
 * Checks whether or not a given loop condition info does not have the modified
 * flag.
 *
 * @param {LoopConditionInfo} condition - A loop condition info to check.
 * @returns {boolean} `true` if the loop condition info is "unmodified".
 */
function isUnmodified(condition) {
    return !condition.modified;
}

/**
 * Checks whether or not a given loop condition info does not have the modified
 * flag and does not have the group this condition belongs to.
 *
 * @param {LoopConditionInfo} condition - A loop condition info to check.
 * @returns {boolean} `true` if the loop condition info is "unmodified".
 */
function isUnmodifiedAndNotBelongToGroup(condition) {
    return !(condition.modified || condition.group);
}

/**
 * Checks whether or not a given reference is inside of a given node.
 *
 * @param {ASTNode} node - A node to check.
 * @param {eslint-scope.Reference} reference - A reference to check.
 * @returns {boolean} `true` if the reference is inside of the node.
 */
function isInRange(node, reference) {
    const or = node.range;
    const ir = reference.identifier.range;

    return or[0] <= ir[0] && ir[1] <= or[1];
}

/**
 * Checks whether or not a given reference is inside of a loop node's condition.
 *
 * @param {ASTNode} node - A node to check.
 * @param {eslint-scope.Reference} reference - A reference to check.
 * @returns {boolean} `true` if the reference is inside of the loop node's
 *      condition.
 */
const isInLoop = {
    WhileStatement: isInRange,
    DoWhileStatement: isInRange,
    ForStatement(node, reference) {
        return (
            isInRange(node, reference) &&
            !(node.init && isInRange(node.init, reference))
        );
    }
};

/**
 * Gets the function which encloses a given reference.
 * This supports only FunctionDeclaration.
 *
 * @param {eslint-scope.Reference} reference - A reference to get.
 * @returns {ASTNode|null} The function node or null.
 */
function getEncloseFunctionDeclaration(reference) {
    let node = reference.identifier;

    while (node) {
        if (node.type === "FunctionDeclaration") {
            return node.id ? node : null;
        }

        node = node.parent;
    }

    return null;
}

/**
 * Updates the "modified" flags of given loop conditions with given modifiers.
 *
 * @param {LoopConditionInfo[]} conditions - The loop conditions to be updated.
 * @param {eslint-scope.Reference[]} modifiers - The references to update.
 * @returns {void}
 */
function updateModifiedFlag(conditions, modifiers) {

    for (let i = 0; i < conditions.length; ++i) {
        const condition = conditions[i];

        for (let j = 0; !condition.modified && j < modifiers.length; ++j) {
            const modifier = modifiers[j];
            let funcNode, funcVar;

            /*
             * Besides checking for the condition being in the loop, we want to
             * check the function that this modifier is belonging to is called
             * in the loop.
             * FIXME: This should probably be extracted to a function.
             */
            const inLoop = condition.isInLoop(modifier) || Boolean(
                (funcNode = getEncloseFunctionDeclaration(modifier)) &&
                (funcVar = astUtils.getVariableByName(modifier.from.upper, funcNode.id.name)) &&
                funcVar.references.some(condition.isInLoop)
            );

            condition.modified = inLoop;
        }
    }
}

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

module.exports = {
    meta: {
        docs: {
            description: "disallow unmodified loop conditions",
            category: "Best Practices",
            recommended: false,
            url: "https://eslint.org/docs/rules/no-unmodified-loop-condition"
        },

        schema: []
    },

    create(context) {
        const sourceCode = context.getSourceCode();
        let groupMap = null;

        /**
         * Reports a given condition info.
         *
         * @param {LoopConditionInfo} condition - A loop condition info to report.
         * @returns {void}
         */
        function report(condition) {
            const node = condition.reference.identifier;

            context.report({
                node,
                message: "'{{name}}' is not modified in this loop.",
                data: node
            });
        }

        /**
         * Registers given conditions to the group the condition belongs to.
         *
         * @param {LoopConditionInfo[]} conditions - A loop condition info to
         *      register.
         * @returns {void}
         */
        function registerConditionsToGroup(conditions) {
            for (let i = 0; i < conditions.length; ++i) {
                const condition = conditions[i];

                if (condition.group) {
                    let group = groupMap.get(condition.group);

                    if (!group) {
                        group = [];
                        groupMap.set(condition.group, group);
                    }
                    group.push(condition);
                }
            }
        }

        /**
         * Reports references which are inside of unmodified groups.
         *
         * @param {LoopConditionInfo[]} conditions - A loop condition info to report.
         * @returns {void}
         */
        function checkConditionsInGroup(conditions) {
            if (conditions.every(isUnmodified)) {
                conditions.forEach(report);
            }
        }

        /**
         * Checks whether or not a given group node has any dynamic elements.
         *
         * @param {ASTNode} root - A node to check.
         *      This node is one of BinaryExpression or ConditionalExpression.
         * @returns {boolean} `true` if the node is dynamic.
         */
        function hasDynamicExpressions(root) {
            let retv = false;

            Traverser.traverse(root, {
                visitorKeys: sourceCode.visitorKeys,
                enter(node) {
                    if (DYNAMIC_PATTERN.test(node.type)) {
                        retv = true;
                        this.break();
                    } else if (SKIP_PATTERN.test(node.type)) {
                        this.skip();
                    }
                }
            });

            return retv;
        }

        /**
         * Creates the loop condition information from a given reference.
         *
         * @param {eslint-scope.Reference} reference - A reference to create.
         * @returns {LoopConditionInfo|null} Created loop condition info, or null.
         */
        function toLoopCondition(reference) {
            if (reference.init) {
                return null;
            }

            let group = null;
            let child = reference.identifier;
            let node = child.parent;

            while (node) {
                if (SENTINEL_PATTERN.test(node.type)) {
                    if (LOOP_PATTERN.test(node.type) && node.test === child) {

                        // This reference is inside of a loop condition.
                        return {
                            reference,
                            group,
                            isInLoop: isInLoop[node.type].bind(null, node),
                            modified: false
                        };
                    }

                    // This reference is outside of a loop condition.
                    break;
                }

                /*
                 * If it's inside of a group, OK if either operand is modified.
                 * So stores the group this reference belongs to.
                 */
                if (GROUP_PATTERN.test(node.type)) {

                    // If this expression is dynamic, no need to check.
                    if (hasDynamicExpressions(node)) {
                        break;
                    } else {
                        group = node;
                    }
                }

                child = node;
                node = node.parent;
            }

            return null;
        }

        /**
         * Finds unmodified references which are inside of a loop condition.
         * Then reports the references which are outside of groups.
         *
         * @param {eslint-scope.Variable} variable - A variable to report.
         * @returns {void}
         */
        function checkReferences(variable) {

            // Gets references that exist in loop conditions.
            const conditions = variable
                .references
                .map(toLoopCondition)
                .filter(Boolean);

            if (conditions.length === 0) {
                return;
            }

            // Registers the conditions to belonging groups.
            registerConditionsToGroup(conditions);

            // Check the conditions are modified.
            const modifiers = variable.references.filter(isWriteReference);

            if (modifiers.length > 0) {
                updateModifiedFlag(conditions, modifiers);
            }

            /*
             * Reports the conditions which are not belonging to groups.
             * Others will be reported after all variables are done.
             */
            conditions
                .filter(isUnmodifiedAndNotBelongToGroup)
                .forEach(report);
        }

        return {
            "Program:exit"() {
                const queue = [context.getScope()];

                groupMap = new Map();

                let scope;

                while ((scope = queue.pop())) {
                    pushAll(queue, scope.childScopes);
                    scope.variables.forEach(checkReferences);
                }

                groupMap.forEach(checkConditionsInGroup);
                groupMap = null;
            }
        };
    }
};
