/**
 * @fileoverview Rule to disallow unused labels.
 * @author Toru Nagashima
 * @copyright 2016 Toru Nagashima. All rights reserved.
 * See LICENSE file in root directory for full license.
 */

"use strict";

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

module.exports = function(context) {
    var scopeInfo = null;

    /**
     * Adds a scope info to the stack.
     *
     * @param {ASTNode} node - A node to add. This is a LabeledStatement.
     * @returns {void}
     */
    function enterLabeledScope(node) {
        scopeInfo = {
            label: node.label.name,
            used: false,
            upper: scopeInfo
        };
    }

    /**
     * Removes the top of the stack.
     * At the same time, this reports the label if it's never used.
     *
     * @param {ASTNode} node - A node to report. This is a LabeledStatement.
     * @returns {void}
     */
    function exitLabeledScope(node) {
        if (!scopeInfo.used) {
            context.report({
                node: node.label,
                message: "'{{name}}:' is defined but never used.",
                data: node.label
            });
        }

        scopeInfo = scopeInfo.upper;
    }

    /**
     * Marks the label of a given node as used.
     *
     * @param {ASTNode} node - A node to mark. This is a BreakStatement or
     *      ContinueStatement.
     * @returns {void}
     */
    function markAsUsed(node) {
        if (!node.label) {
            return;
        }

        var label = node.label.name;
        var info = scopeInfo;
        while (info) {
            if (info.label === label) {
                info.used = true;
                break;
            }
            info = info.upper;
        }
    }

    return {
        "LabeledStatement": enterLabeledScope,
        "LabeledStatement:exit": exitLabeledScope,
        "BreakStatement": markAsUsed,
        "ContinueStatement": markAsUsed
    };
};

module.exports.schema = [];
