"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
 * @typedef {{
 *   comment: string,
 *   context: string,
 *   message: string,
 *   minimum: import('../iterateJsdoc.js').Integer
 * }} ContextObject
 */

/**
 * @typedef {string|ContextObject} Context
 */

/**
 * @param {import('../iterateJsdoc.js').StateObject} state
 * @returns {void}
 */
const setDefaults = state => {
  if (!state.selectorMap) {
    state.selectorMap = {};
  }
};

/**
 * @param {import('../iterateJsdoc.js').StateObject} state
 * @param {string} selector
 * @param {string} comment
 * @returns {void}
 */
const incrementSelector = (state, selector, comment) => {
  if (!state.selectorMap[selector]) {
    state.selectorMap[selector] = {};
  }
  if (!state.selectorMap[selector][comment]) {
    state.selectorMap[selector][comment] = 0;
  }
  state.selectorMap[selector][comment]++;
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
  context,
  info: {
    comment
  },
  state,
  utils
}) => {
  if (!context.options[0]) {
    // Handle error later
    return;
  }

  /**
   * @type {Context[]}
   */
  const contexts = context.options[0].contexts;
  const {
    contextStr
  } = utils.findContext(contexts, comment);
  setDefaults(state);
  incrementSelector(state, contextStr, String(comment));
}, {
  contextSelected: true,
  exit({
    context,
    settings,
    state
  }) {
    if (!context.options.length && !settings.contexts) {
      context.report({
        loc: {
          end: {
            column: 1,
            line: 1
          },
          start: {
            column: 1,
            line: 1
          }
        },
        message: 'Rule `no-missing-syntax` is missing a `contexts` option.'
      });
      return;
    }
    setDefaults(state);

    /**
     * @type {Context[]}
     */
    const contexts = (context.options[0] ?? {}).contexts ?? settings?.contexts;

    // Report when MISSING
    contexts.some(cntxt => {
      const contextStr = typeof cntxt === 'object' ? cntxt.context ?? 'any' : cntxt;
      const comment = typeof cntxt === 'string' ? '' : cntxt?.comment ?? '';
      const contextKey = contextStr === 'any' ? 'undefined' : contextStr;
      if ((!state.selectorMap[contextKey] || !state.selectorMap[contextKey][comment] || state.selectorMap[contextKey][comment] < (
      // @ts-expect-error comment would need an object, not string
      cntxt?.minimum ?? 1)) && (contextStr !== 'any' || Object.values(state.selectorMap).every(cmmnt => {
        return !cmmnt[comment] || cmmnt[comment] < (
        // @ts-expect-error comment would need an object, not string
        cntxt?.minimum ?? 1);
      }))) {
        const message = typeof cntxt === 'string' ? 'Syntax is required: {{context}}' : cntxt?.message ?? 'Syntax is required: {{context}}' + (comment ? ' with {{comment}}' : '');
        context.report({
          data: {
            comment,
            context: contextStr
          },
          loc: {
            end: {
              column: 1,
              line: 1
            },
            start: {
              column: 1,
              line: 1
            }
          },
          message
        });
        return true;
      }
      return false;
    });
  },
  matchContext: true,
  meta: {
    docs: {
      description: 'Reports when certain comment structures are always expected.',
      url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-missing-syntax.md#repos-sticky-header'
    },
    schema: [{
      additionalProperties: false,
      properties: {
        contexts: {
          description: `Set this to an array of strings representing the AST context (or an object with
optional \`context\` and \`comment\` properties) where you wish the rule to be applied.

\`context\` defaults to \`any\` and \`comment\` defaults to no specific comment context.

Use the \`minimum\` property (defaults to 1) to indicate how many are required
for the rule to be reported.

Use the \`message\` property to indicate the specific error to be shown when an
error is reported for that context being found missing. You may use
\`{{context}}\` and \`{{comment}}\` with such messages. Defaults to
\`"Syntax is required: {{context}}"\`, or with a comment, to
\`"Syntax is required: {{context}} with {{comment}}"\`.

Set to \`"any"\` if you want the rule to apply to any JSDoc block throughout
your files (as is necessary for finding function blocks not attached to a
function declaration or expression, i.e., \`@callback\` or \`@function\` (or its
aliases \`@func\` or \`@method\`) (including those associated with an \`@interface\`).

See the ["AST and Selectors"](../#advanced-ast-and-selectors)
section of our Advanced docs for more on the expected format.`,
          items: {
            anyOf: [{
              type: 'string'
            }, {
              additionalProperties: false,
              properties: {
                comment: {
                  type: 'string'
                },
                context: {
                  type: 'string'
                },
                message: {
                  type: 'string'
                },
                minimum: {
                  type: 'integer'
                }
              },
              type: 'object'
            }]
          },
          type: 'array'
        }
      },
      type: 'object'
    }],
    type: 'suggestion'
  }
});
module.exports = exports.default;
//# sourceMappingURL=noMissingSyntax.cjs.map