/**
 * @fileoverview Rule to enforce correct placement of at-rules.
 * @author thecalamiity
 */
//-----------------------------------------------------------------------------
// Type Definitions
//-----------------------------------------------------------------------------
/**
 * @import { CSSRuleDefinition } from "../types.js"
 * @typedef {"invalidCharsetPlacement" | "invalidImportPlacement" | "invalidNamespacePlacement"} NoInvalidAtRulePlacementMessageIds
 * @typedef {CSSRuleDefinition<{ RuleOptions: [], MessageIds: NoInvalidAtRulePlacementMessageIds }>} NoInvalidAtRulePlacementRuleDefinition
 */
//-----------------------------------------------------------------------------
// Rule Definition
//-----------------------------------------------------------------------------
export default /** @satisfies {NoInvalidAtRulePlacementRuleDefinition} */ ({
    meta: {
        type: "problem",
        docs: {
            description: "Disallow invalid placement of at-rules",
            recommended: true,
            url: "https://github.com/eslint/css/blob/main/docs/rules/no-invalid-at-rule-placement.md",
        },
        messages: {
            invalidCharsetPlacement: "@charset must be placed at the very beginning of the stylesheet, before any rules, comments, or whitespace.",
            invalidImportPlacement: "@import must be placed before all other rules, except @charset and @layer statements.",
            invalidNamespacePlacement: "@namespace must be placed before all other rules, except @charset and @import.",
        },
    },
    create(context) {
        let hasSeenNonImportRule = false;
        let hasSeenLayerBlock = false;
        let hasSeenLayer = false;
        let hasSeenNamespace = false;
        return {
            Atrule(node) {
                const name = node.name.toLowerCase();
                if (name === "charset") {
                    if (node.loc.start.line !== 1 ||
                        node.loc.start.column !== 1) {
                        context.report({
                            node,
                            messageId: "invalidCharsetPlacement",
                        });
                    }
                    return;
                }
                if (name === "layer") {
                    if (node.block) {
                        hasSeenLayerBlock = true;
                    }
                    hasSeenLayer = true;
                    return;
                }
                if (name === "namespace") {
                    if (hasSeenNonImportRule || hasSeenLayer) {
                        context.report({
                            node,
                            messageId: "invalidNamespacePlacement",
                        });
                    }
                    hasSeenNamespace = true;
                    return;
                }
                if (name === "import") {
                    if (hasSeenNonImportRule ||
                        hasSeenNamespace ||
                        hasSeenLayerBlock) {
                        context.report({
                            node,
                            messageId: "invalidImportPlacement",
                        });
                    }
                    return;
                }
                hasSeenNonImportRule = true;
            },
            Rule() {
                hasSeenNonImportRule = true;
            },
        };
    },
});
