/**
 * @fileoverview Rule to enforce spacing before and after keywords.
 * @author Toru Nagashima
 */

"use strict";

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

const astUtils = require("./utils/ast-utils"),
    keywords = require("./utils/keywords");

//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------

const PREV_TOKEN = /^[)\]}>]$/u;
const NEXT_TOKEN = /^(?:[([{<~!]|\+\+?|--?)$/u;
const PREV_TOKEN_M = /^[)\]}>*]$/u;
const NEXT_TOKEN_M = /^[{*]$/u;
const TEMPLATE_OPEN_PAREN = /\$\{$/u;
const TEMPLATE_CLOSE_PAREN = /^\}/u;
const CHECK_TYPE = /^(?:JSXElement|RegularExpression|String|Template)$/u;
const KEYS = keywords.concat(["as", "async", "await", "from", "get", "let", "of", "set", "yield"]);

// check duplications.
(function() {
    KEYS.sort();
    for (let i = 1; i < KEYS.length; ++i) {
        if (KEYS[i] === KEYS[i - 1]) {
            throw new Error(`Duplication was found in the keyword list: ${KEYS[i]}`);
        }
    }
}());

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

/**
 * Checks whether or not a given token is a "Template" token ends with "${".
 *
 * @param {Token} token - A token to check.
 * @returns {boolean} `true` if the token is a "Template" token ends with "${".
 */
function isOpenParenOfTemplate(token) {
    return token.type === "Template" && TEMPLATE_OPEN_PAREN.test(token.value);
}

/**
 * Checks whether or not a given token is a "Template" token starts with "}".
 *
 * @param {Token} token - A token to check.
 * @returns {boolean} `true` if the token is a "Template" token starts with "}".
 */
function isCloseParenOfTemplate(token) {
    return token.type === "Template" && TEMPLATE_CLOSE_PAREN.test(token.value);
}

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

module.exports = {
    meta: {
        type: "layout",

        docs: {
            description: "enforce consistent spacing before and after keywords",
            category: "Stylistic Issues",
            recommended: false,
            url: "https://eslint.org/docs/rules/keyword-spacing"
        },

        fixable: "whitespace",

        schema: [
            {
                type: "object",
                properties: {
                    before: { type: "boolean", default: true },
                    after: { type: "boolean", default: true },
                    overrides: {
                        type: "object",
                        properties: KEYS.reduce((retv, key) => {
                            retv[key] = {
                                type: "object",
                                properties: {
                                    before: { type: "boolean", default: true },
                                    after: { type: "boolean", default: true }
                                },
                                additionalProperties: false
                            };
                            return retv;
                        }, {}),
                        additionalProperties: false
                    }
                },
                additionalProperties: false
            }
        ],
        messages: {
            expectedBefore: "Expected space(s) before \"{{value}}\".",
            expectedAfter: "Expected space(s) after \"{{value}}\".",
            unexpectedBefore: "Unexpected space(s) before \"{{value}}\".",
            unexpectedAfter: "Unexpected space(s) after \"{{value}}\"."
        }
    },

    create(context) {
        const sourceCode = context.getSourceCode();

        /**
         * Reports a given token if there are not space(s) before the token.
         *
         * @param {Token} token - A token to report.
         * @param {RegExp} pattern - A pattern of the previous token to check.
         * @returns {void}
         */
        function expectSpaceBefore(token, pattern) {
            const prevToken = sourceCode.getTokenBefore(token);

            if (prevToken &&
                (CHECK_TYPE.test(prevToken.type) || pattern.test(prevToken.value)) &&
                !isOpenParenOfTemplate(prevToken) &&
                astUtils.isTokenOnSameLine(prevToken, token) &&
                !sourceCode.isSpaceBetweenTokens(prevToken, token)
            ) {
                context.report({
                    loc: token.loc.start,
                    messageId: "expectedBefore",
                    data: token,
                    fix(fixer) {
                        return fixer.insertTextBefore(token, " ");
                    }
                });
            }
        }

        /**
         * Reports a given token if there are space(s) before the token.
         *
         * @param {Token} token - A token to report.
         * @param {RegExp} pattern - A pattern of the previous token to check.
         * @returns {void}
         */
        function unexpectSpaceBefore(token, pattern) {
            const prevToken = sourceCode.getTokenBefore(token);

            if (prevToken &&
                (CHECK_TYPE.test(prevToken.type) || pattern.test(prevToken.value)) &&
                !isOpenParenOfTemplate(prevToken) &&
                astUtils.isTokenOnSameLine(prevToken, token) &&
                sourceCode.isSpaceBetweenTokens(prevToken, token)
            ) {
                context.report({
                    loc: token.loc.start,
                    messageId: "unexpectedBefore",
                    data: token,
                    fix(fixer) {
                        return fixer.removeRange([prevToken.range[1], token.range[0]]);
                    }
                });
            }
        }

        /**
         * Reports a given token if there are not space(s) after the token.
         *
         * @param {Token} token - A token to report.
         * @param {RegExp} pattern - A pattern of the next token to check.
         * @returns {void}
         */
        function expectSpaceAfter(token, pattern) {
            const nextToken = sourceCode.getTokenAfter(token);

            if (nextToken &&
                (CHECK_TYPE.test(nextToken.type) || pattern.test(nextToken.value)) &&
                !isCloseParenOfTemplate(nextToken) &&
                astUtils.isTokenOnSameLine(token, nextToken) &&
                !sourceCode.isSpaceBetweenTokens(token, nextToken)
            ) {
                context.report({
                    loc: token.loc.start,
                    messageId: "expectedAfter",
                    data: token,
                    fix(fixer) {
                        return fixer.insertTextAfter(token, " ");
                    }
                });
            }
        }

        /**
         * Reports a given token if there are space(s) after the token.
         *
         * @param {Token} token - A token to report.
         * @param {RegExp} pattern - A pattern of the next token to check.
         * @returns {void}
         */
        function unexpectSpaceAfter(token, pattern) {
            const nextToken = sourceCode.getTokenAfter(token);

            if (nextToken &&
                (CHECK_TYPE.test(nextToken.type) || pattern.test(nextToken.value)) &&
                !isCloseParenOfTemplate(nextToken) &&
                astUtils.isTokenOnSameLine(token, nextToken) &&
                sourceCode.isSpaceBetweenTokens(token, nextToken)
            ) {
                context.report({
                    loc: token.loc.start,
                    messageId: "unexpectedAfter",
                    data: token,
                    fix(fixer) {
                        return fixer.removeRange([token.range[1], nextToken.range[0]]);
                    }
                });
            }
        }

        /**
         * Parses the option object and determines check methods for each keyword.
         *
         * @param {Object|undefined} options - The option object to parse.
         * @returns {Object} - Normalized option object.
         *      Keys are keywords (there are for every keyword).
         *      Values are instances of `{"before": function, "after": function}`.
         */
        function parseOptions(options = {}) {
            const before = options.before !== false;
            const after = options.after !== false;
            const defaultValue = {
                before: before ? expectSpaceBefore : unexpectSpaceBefore,
                after: after ? expectSpaceAfter : unexpectSpaceAfter
            };
            const overrides = (options && options.overrides) || {};
            const retv = Object.create(null);

            for (let i = 0; i < KEYS.length; ++i) {
                const key = KEYS[i];
                const override = overrides[key];

                if (override) {
                    const thisBefore = ("before" in override) ? override.before : before;
                    const thisAfter = ("after" in override) ? override.after : after;

                    retv[key] = {
                        before: thisBefore ? expectSpaceBefore : unexpectSpaceBefore,
                        after: thisAfter ? expectSpaceAfter : unexpectSpaceAfter
                    };
                } else {
                    retv[key] = defaultValue;
                }
            }

            return retv;
        }

        const checkMethodMap = parseOptions(context.options[0]);

        /**
         * Reports a given token if usage of spacing followed by the token is
         * invalid.
         *
         * @param {Token} token - A token to report.
         * @param {RegExp|undefined} pattern - Optional. A pattern of the previous
         *      token to check.
         * @returns {void}
         */
        function checkSpacingBefore(token, pattern) {
            checkMethodMap[token.value].before(token, pattern || PREV_TOKEN);
        }

        /**
         * Reports a given token if usage of spacing preceded by the token is
         * invalid.
         *
         * @param {Token} token - A token to report.
         * @param {RegExp|undefined} pattern - Optional. A pattern of the next
         *      token to check.
         * @returns {void}
         */
        function checkSpacingAfter(token, pattern) {
            checkMethodMap[token.value].after(token, pattern || NEXT_TOKEN);
        }

        /**
         * Reports a given token if usage of spacing around the token is invalid.
         *
         * @param {Token} token - A token to report.
         * @returns {void}
         */
        function checkSpacingAround(token) {
            checkSpacingBefore(token);
            checkSpacingAfter(token);
        }

        /**
         * Reports the first token of a given node if the first token is a keyword
         * and usage of spacing around the token is invalid.
         *
         * @param {ASTNode|null} node - A node to report.
         * @returns {void}
         */
        function checkSpacingAroundFirstToken(node) {
            const firstToken = node && sourceCode.getFirstToken(node);

            if (firstToken && firstToken.type === "Keyword") {
                checkSpacingAround(firstToken);
            }
        }

        /**
         * Reports the first token of a given node if the first token is a keyword
         * and usage of spacing followed by the token is invalid.
         *
         * This is used for unary operators (e.g. `typeof`), `function`, and `super`.
         * Other rules are handling usage of spacing preceded by those keywords.
         *
         * @param {ASTNode|null} node - A node to report.
         * @returns {void}
         */
        function checkSpacingBeforeFirstToken(node) {
            const firstToken = node && sourceCode.getFirstToken(node);

            if (firstToken && firstToken.type === "Keyword") {
                checkSpacingBefore(firstToken);
            }
        }

        /**
         * Reports the previous token of a given node if the token is a keyword and
         * usage of spacing around the token is invalid.
         *
         * @param {ASTNode|null} node - A node to report.
         * @returns {void}
         */
        function checkSpacingAroundTokenBefore(node) {
            if (node) {
                const token = sourceCode.getTokenBefore(node, astUtils.isKeywordToken);

                checkSpacingAround(token);
            }
        }

        /**
         * Reports `async` or `function` keywords of a given node if usage of
         * spacing around those keywords is invalid.
         *
         * @param {ASTNode} node - A node to report.
         * @returns {void}
         */
        function checkSpacingForFunction(node) {
            const firstToken = node && sourceCode.getFirstToken(node);

            if (firstToken &&
                ((firstToken.type === "Keyword" && firstToken.value === "function") ||
                firstToken.value === "async")
            ) {
                checkSpacingBefore(firstToken);
            }
        }

        /**
         * Reports `class` and `extends` keywords of a given node if usage of
         * spacing around those keywords is invalid.
         *
         * @param {ASTNode} node - A node to report.
         * @returns {void}
         */
        function checkSpacingForClass(node) {
            checkSpacingAroundFirstToken(node);
            checkSpacingAroundTokenBefore(node.superClass);
        }

        /**
         * Reports `if` and `else` keywords of a given node if usage of spacing
         * around those keywords is invalid.
         *
         * @param {ASTNode} node - A node to report.
         * @returns {void}
         */
        function checkSpacingForIfStatement(node) {
            checkSpacingAroundFirstToken(node);
            checkSpacingAroundTokenBefore(node.alternate);
        }

        /**
         * Reports `try`, `catch`, and `finally` keywords of a given node if usage
         * of spacing around those keywords is invalid.
         *
         * @param {ASTNode} node - A node to report.
         * @returns {void}
         */
        function checkSpacingForTryStatement(node) {
            checkSpacingAroundFirstToken(node);
            checkSpacingAroundFirstToken(node.handler);
            checkSpacingAroundTokenBefore(node.finalizer);
        }

        /**
         * Reports `do` and `while` keywords of a given node if usage of spacing
         * around those keywords is invalid.
         *
         * @param {ASTNode} node - A node to report.
         * @returns {void}
         */
        function checkSpacingForDoWhileStatement(node) {
            checkSpacingAroundFirstToken(node);
            checkSpacingAroundTokenBefore(node.test);
        }

        /**
         * Reports `for` and `in` keywords of a given node if usage of spacing
         * around those keywords is invalid.
         *
         * @param {ASTNode} node - A node to report.
         * @returns {void}
         */
        function checkSpacingForForInStatement(node) {
            checkSpacingAroundFirstToken(node);
            checkSpacingAroundTokenBefore(node.right);
        }

        /**
         * Reports `for` and `of` keywords of a given node if usage of spacing
         * around those keywords is invalid.
         *
         * @param {ASTNode} node - A node to report.
         * @returns {void}
         */
        function checkSpacingForForOfStatement(node) {
            if (node.await) {
                checkSpacingBefore(sourceCode.getFirstToken(node, 0));
                checkSpacingAfter(sourceCode.getFirstToken(node, 1));
            } else {
                checkSpacingAroundFirstToken(node);
            }
            checkSpacingAround(sourceCode.getTokenBefore(node.right, astUtils.isNotOpeningParenToken));
        }

        /**
         * Reports `import`, `export`, `as`, and `from` keywords of a given node if
         * usage of spacing around those keywords is invalid.
         *
         * This rule handles the `*` token in module declarations.
         *
         *     import*as A from "./a"; /*error Expected space(s) after "import".
         *                               error Expected space(s) before "as".
         *
         * @param {ASTNode} node - A node to report.
         * @returns {void}
         */
        function checkSpacingForModuleDeclaration(node) {
            const firstToken = sourceCode.getFirstToken(node);

            checkSpacingBefore(firstToken, PREV_TOKEN_M);
            checkSpacingAfter(firstToken, NEXT_TOKEN_M);

            if (node.type === "ExportDefaultDeclaration") {
                checkSpacingAround(sourceCode.getTokenAfter(firstToken));
            }

            if (node.source) {
                const fromToken = sourceCode.getTokenBefore(node.source);

                checkSpacingBefore(fromToken, PREV_TOKEN_M);
                checkSpacingAfter(fromToken, NEXT_TOKEN_M);
            }
        }

        /**
         * Reports `as` keyword of a given node if usage of spacing around this
         * keyword is invalid.
         *
         * @param {ASTNode} node - A node to report.
         * @returns {void}
         */
        function checkSpacingForImportNamespaceSpecifier(node) {
            const asToken = sourceCode.getFirstToken(node, 1);

            checkSpacingBefore(asToken, PREV_TOKEN_M);
        }

        /**
         * Reports `static`, `get`, and `set` keywords of a given node if usage of
         * spacing around those keywords is invalid.
         *
         * @param {ASTNode} node - A node to report.
         * @returns {void}
         */
        function checkSpacingForProperty(node) {
            if (node.static) {
                checkSpacingAroundFirstToken(node);
            }
            if (node.kind === "get" ||
                node.kind === "set" ||
                (
                    (node.method || node.type === "MethodDefinition") &&
                    node.value.async
                )
            ) {
                const token = sourceCode.getTokenBefore(
                    node.key,
                    tok => {
                        switch (tok.value) {
                            case "get":
                            case "set":
                            case "async":
                                return true;
                            default:
                                return false;
                        }
                    }
                );

                if (!token) {
                    throw new Error("Failed to find token get, set, or async beside method name");
                }


                checkSpacingAround(token);
            }
        }

        /**
         * Reports `await` keyword of a given node if usage of spacing before
         * this keyword is invalid.
         *
         * @param {ASTNode} node - A node to report.
         * @returns {void}
         */
        function checkSpacingForAwaitExpression(node) {
            checkSpacingBefore(sourceCode.getFirstToken(node));
        }

        return {

            // Statements
            DebuggerStatement: checkSpacingAroundFirstToken,
            WithStatement: checkSpacingAroundFirstToken,

            // Statements - Control flow
            BreakStatement: checkSpacingAroundFirstToken,
            ContinueStatement: checkSpacingAroundFirstToken,
            ReturnStatement: checkSpacingAroundFirstToken,
            ThrowStatement: checkSpacingAroundFirstToken,
            TryStatement: checkSpacingForTryStatement,

            // Statements - Choice
            IfStatement: checkSpacingForIfStatement,
            SwitchStatement: checkSpacingAroundFirstToken,
            SwitchCase: checkSpacingAroundFirstToken,

            // Statements - Loops
            DoWhileStatement: checkSpacingForDoWhileStatement,
            ForInStatement: checkSpacingForForInStatement,
            ForOfStatement: checkSpacingForForOfStatement,
            ForStatement: checkSpacingAroundFirstToken,
            WhileStatement: checkSpacingAroundFirstToken,

            // Statements - Declarations
            ClassDeclaration: checkSpacingForClass,
            ExportNamedDeclaration: checkSpacingForModuleDeclaration,
            ExportDefaultDeclaration: checkSpacingForModuleDeclaration,
            ExportAllDeclaration: checkSpacingForModuleDeclaration,
            FunctionDeclaration: checkSpacingForFunction,
            ImportDeclaration: checkSpacingForModuleDeclaration,
            VariableDeclaration: checkSpacingAroundFirstToken,

            // Expressions
            ArrowFunctionExpression: checkSpacingForFunction,
            AwaitExpression: checkSpacingForAwaitExpression,
            ClassExpression: checkSpacingForClass,
            FunctionExpression: checkSpacingForFunction,
            NewExpression: checkSpacingBeforeFirstToken,
            Super: checkSpacingBeforeFirstToken,
            ThisExpression: checkSpacingBeforeFirstToken,
            UnaryExpression: checkSpacingBeforeFirstToken,
            YieldExpression: checkSpacingBeforeFirstToken,

            // Others
            ImportNamespaceSpecifier: checkSpacingForImportNamespaceSpecifier,
            MethodDefinition: checkSpacingForProperty,
            Property: checkSpacingForProperty
        };
    }
};
