/**
 * @fileoverview Rule to disallow data rows in a GitHub Flavored Markdown table from having more cells than the header row
 * @author Sweta Tanwar (@SwetaTanwar)
 */
//-----------------------------------------------------------------------------
// Type Definitions
//-----------------------------------------------------------------------------
/**
 * @import { MarkdownRuleDefinition } from "../types.js";
 * @typedef {"extraCells" | "missingCells"} TableColumnCountMessageIds
 * @typedef {[{ checkMissingCells?: boolean }]} TableColumnCountOptions
 * @typedef {MarkdownRuleDefinition<{ RuleOptions: TableColumnCountOptions, MessageIds: TableColumnCountMessageIds }>} TableColumnCountRuleDefinition
 */
//-----------------------------------------------------------------------------
// Rule Definition
//-----------------------------------------------------------------------------
export default /** @satisfies {TableColumnCountRuleDefinition} */ ({
    meta: {
        type: "problem",
        docs: {
            recommended: true,
            description: "Disallow data rows in a GitHub Flavored Markdown table from having more cells than the header row",
            url: "https://github.com/eslint/markdown/blob/main/docs/rules/table-column-count.md",
        },
        messages: {
            extraCells: "Table column count mismatch (Expected: {{expectedCells}}, Actual: {{actualCells}}), extra data starting here will be ignored.",
            missingCells: "Table column count mismatch (Expected: {{expectedCells}}, Actual: {{actualCells}}), row might be missing data.",
        },
        schema: [
            {
                type: "object",
                properties: {
                    checkMissingCells: {
                        type: "boolean",
                    },
                },
                additionalProperties: false,
            },
        ],
        defaultOptions: [{ checkMissingCells: false }],
    },
    create(context) {
        const [{ checkMissingCells }] = context.options;
        return {
            table(node) {
                if (node.children.length < 1) {
                    return;
                }
                const headerRow = node.children[0];
                const expectedCellsLength = headerRow.children.length;
                for (let i = 1; i < node.children.length; i++) {
                    const currentRow = node.children[i];
                    const actualCellsLength = currentRow.children.length;
                    const lastActualCellNode = currentRow.children[actualCellsLength - 1];
                    if (actualCellsLength > expectedCellsLength) {
                        const firstExtraCellNode = currentRow.children[expectedCellsLength];
                        context.report({
                            loc: {
                                start: firstExtraCellNode.position.start,
                                end: lastActualCellNode.position.end,
                            },
                            messageId: "extraCells",
                            data: {
                                actualCells: actualCellsLength,
                                expectedCells: expectedCellsLength,
                            },
                        });
                    }
                    else if (checkMissingCells &&
                        actualCellsLength < expectedCellsLength) {
                        context.report({
                            loc: {
                                start: {
                                    column: lastActualCellNode.position.end.column -
                                        1,
                                    line: lastActualCellNode.position.end.line,
                                },
                                end: currentRow.position.end,
                            },
                            messageId: "missingCells",
                            data: {
                                actualCells: actualCellsLength,
                                expectedCells: expectedCellsLength,
                            },
                        });
                    }
                }
            },
        };
    },
});
