/**
 * @internal
 */
export default {
	tag_option_deprecated: {
		code: 'tag-option-deprecated',
		message: "'tag' option is deprecated — use 'customElement' instead"
	},
	unused_export_let: /**
	 * @param {string} component
	 * @param {string} property
	 */ (component, property) => ({
		code: 'unused-export-let',
		message: `${component} has unused export property '${property}'. If it is for external reference only, please consider using \`export const ${property}\``
	}),
	module_script_reactive_declaration: {
		code: 'module-script-reactive-declaration',
		message: '$: has no effect in a module script'
	},
	non_top_level_reactive_declaration: {
		code: 'non-top-level-reactive-declaration',
		message: '$: has no effect outside of the top-level'
	},
	module_script_variable_reactive_declaration: /** @param {string[]} names */ (names) => ({
		code: 'module-script-reactive-declaration',
		message: `${names.map(/** @param {any} name */ (name) => `"${name}"`).join(', ')} ${
			names.length > 1 ? 'are' : 'is'
		} declared in a module script and will not be reactive`
	}),
	missing_declaration: /**
	 * @param {string} name
	 * @param {boolean} has_script
	 */ (name, has_script) => ({
		code: 'missing-declaration',
		message:
			`'${name}' is not defined` +
			(has_script
				? ''
				: `. Consider adding a <script> block with 'export let ${name}' to declare a prop`)
	}),
	missing_custom_element_compile_options: {
		code: 'missing-custom-element-compile-options',
		message:
			"The 'customElement' option is used when generating a custom element. Did you forget the 'customElement: true' compile option?"
	},
	css_unused_selector: /** @param {string} selector */ (selector) => ({
		code: 'css-unused-selector',
		message: `Unused CSS selector "${selector}"`
	}),
	empty_block: {
		code: 'empty-block',
		message: 'Empty block'
	},
	reactive_component: /** @param {string} name */ (name) => ({
		code: 'reactive-component',
		message: `<${name}/> will not be reactive if ${name} changes. Use <svelte:component this={${name}}/> if you want this reactivity.`
	}),
	component_name_lowercase: /** @param {string} name */ (name) => ({
		code: 'component-name-lowercase',
		message: `<${name}> will be treated as an HTML element unless it begins with a capital letter`
	}),
	avoid_is: {
		code: 'avoid-is',
		message: "The 'is' attribute is not supported cross-browser and should be avoided"
	},
	invalid_html_attribute: /**
	 * @param {string} name
	 * @param {string} suggestion
	 */ (name, suggestion) => ({
		code: 'invalid-html-attribute',
		message: `'${name}' is not a valid HTML attribute. Did you mean '${suggestion}'?`
	}),
	a11y_aria_attributes: /** @param {string} name */ (name) => ({
		code: 'a11y-aria-attributes',
		message: `A11y: <${name}> should not have aria-* attributes`
	}),
	a11y_incorrect_attribute_type: /**
	 * @param {import('aria-query').ARIAPropertyDefinition} schema
	 * @param {string} attribute
	 */ (schema, attribute) => {
		let message;
		switch (schema.type) {
			case 'boolean':
				message = `The value of '${attribute}' must be exactly one of true or false`;
				break;
			case 'id':
				message = `The value of '${attribute}' must be a string that represents a DOM element ID`;
				break;
			case 'idlist':
				message = `The value of '${attribute}' must be a space-separated list of strings that represent DOM element IDs`;
				break;
			case 'tristate':
				message = `The value of '${attribute}' must be exactly one of true, false, or mixed`;
				break;
			case 'token':
				message = `The value of '${attribute}' must be exactly one of ${(schema.values || []).join(
					', '
				)}`;
				break;
			case 'tokenlist':
				message = `The value of '${attribute}' must be a space-separated list of one or more of ${(
					schema.values || []
				).join(', ')}`;
				break;
			default:
				message = `The value of '${attribute}' must be of type ${schema.type}`;
		}
		return {
			code: 'a11y-incorrect-aria-attribute-type',
			message: `A11y: ${message}`
		};
	},
	a11y_unknown_aria_attribute: /**
	 * @param {string} attribute
	 * @param {string} [suggestion]
	 */ (attribute, suggestion) => ({
		code: 'a11y-unknown-aria-attribute',
		message:
			`A11y: Unknown aria attribute 'aria-${attribute}'` +
			(suggestion ? ` (did you mean '${suggestion}'?)` : '')
	}),
	a11y_hidden: /** @param {string} name */ (name) => ({
		code: 'a11y-hidden',
		message: `A11y: <${name}> element should not be hidden`
	}),
	a11y_misplaced_role: /** @param {string} name */ (name) => ({
		code: 'a11y-misplaced-role',
		message: `A11y: <${name}> should not have role attribute`
	}),
	a11y_unknown_role: /**
	 * @param {string | boolean} role
	 * @param {string} [suggestion]
	 */ (role, suggestion) => ({
		code: 'a11y-unknown-role',
		message: `A11y: Unknown role '${role}'` + (suggestion ? ` (did you mean '${suggestion}'?)` : '')
	}),
	a11y_no_abstract_role: /** @param {string | boolean} role */ (role) => ({
		code: 'a11y-no-abstract-role',
		message: `A11y: Abstract role '${role}' is forbidden`
	}),
	a11y_no_redundant_roles: /** @param {string | boolean} role */ (role) => ({
		code: 'a11y-no-redundant-roles',
		message: `A11y: Redundant role '${role}'`
	}),
	a11y_no_static_element_interactions: /**
	 * @param {string} element
	 * @param {string[]} handlers
	 */ (element, handlers) => ({
		code: 'a11y-no-static-element-interactions',
		message: `A11y: <${element}> with ${handlers.join(', ')} ${
			handlers.length === 1 ? 'handler' : 'handlers'
		} must have an ARIA role`
	}),
	a11y_no_interactive_element_to_noninteractive_role: /**
	 * @param {string | boolean} role
	 * @param {string} element
	 */ (role, element) => ({
		code: 'a11y-no-interactive-element-to-noninteractive-role',
		message: `A11y: <${element}> cannot have role '${role}'`
	}),
	a11y_no_noninteractive_element_interactions: /** @param {string} element */ (element) => ({
		code: 'a11y-no-noninteractive-element-interactions',
		message: `A11y: Non-interactive element <${element}> should not be assigned mouse or keyboard event listeners.`
	}),
	a11y_no_noninteractive_element_to_interactive_role: /**
	 * @param {string | boolean} role
	 * @param {string} element
	 */ (role, element) => ({
		code: 'a11y-no-noninteractive-element-to-interactive-role',
		message: `A11y: Non-interactive element <${element}> cannot have interactive role '${role}'`
	}),
	a11y_role_has_required_aria_props: /**
	 * @param {string} role
	 * @param {string[]} props
	 */ (role, props) => ({
		code: 'a11y-role-has-required-aria-props',
		message: `A11y: Elements with the ARIA role "${role}" must have the following attributes defined: ${props
			.map(/** @param {any} name */ (name) => `"${name}"`)
			.join(', ')}`
	}),
	a11y_role_supports_aria_props: /**
	 * @param {string} attribute
	 * @param {string} role
	 * @param {boolean} is_implicit
	 * @param {string} name
	 */ (attribute, role, is_implicit, name) => {
		let message = `The attribute '${attribute}' is not supported by the role '${role}'.`;
		if (is_implicit) {
			message += ` This role is implicit on the element <${name}>.`;
		}
		return {
			code: 'a11y-role-supports-aria-props',
			message: `A11y: ${message}`
		};
	},
	a11y_accesskey: {
		code: 'a11y-accesskey',
		message: 'A11y: Avoid using accesskey'
	},
	a11y_autofocus: {
		code: 'a11y-autofocus',
		message: 'A11y: Avoid using autofocus'
	},
	a11y_misplaced_scope: {
		code: 'a11y-misplaced-scope',
		message: 'A11y: The scope attribute should only be used with <th> elements'
	},
	a11y_positive_tabindex: {
		code: 'a11y-positive-tabindex',
		message: 'A11y: avoid tabindex values above zero'
	},
	a11y_invalid_attribute: /**
	 * @param {string} href_attribute
	 * @param {string} href_value
	 */ (href_attribute, href_value) => ({
		code: 'a11y-invalid-attribute',
		message: `A11y: '${href_value}' is not a valid ${href_attribute} attribute`
	}),
	a11y_missing_attribute: /**
	 * @param {string} name
	 * @param {string} article
	 * @param {string} sequence
	 */ (name, article, sequence) => ({
		code: 'a11y-missing-attribute',
		message: `A11y: <${name}> element should have ${article} ${sequence} attribute`
	}),
	a11y_autocomplete_valid: /**
	 * @param {null | true | string} type
	 * @param {null | true | string} value
	 */ (type, value) => ({
		code: 'a11y-autocomplete-valid',
		message: `A11y: The value '${value}' is not supported by the attribute 'autocomplete' on element <input type="${
			type || '...'
		}">`
	}),
	a11y_img_redundant_alt: {
		code: 'a11y-img-redundant-alt',
		message: 'A11y: Screenreaders already announce <img> elements as an image.'
	},
	a11y_interactive_supports_focus: /** @param {string} role */ (role) => ({
		code: 'a11y-interactive-supports-focus',
		message: `A11y: Elements with the '${role}' interactive role must have a tabindex value.`
	}),
	a11y_label_has_associated_control: {
		code: 'a11y-label-has-associated-control',
		message: 'A11y: A form label must be associated with a control.'
	},
	a11y_media_has_caption: {
		code: 'a11y-media-has-caption',
		message: 'A11y: <video> elements must have a <track kind="captions">'
	},
	a11y_distracting_elements: /** @param {string} name */ (name) => ({
		code: 'a11y-distracting-elements',
		message: `A11y: Avoid <${name}> elements`
	}),
	a11y_structure_immediate: {
		code: 'a11y-structure',
		message: 'A11y: <figcaption> must be an immediate child of <figure>'
	},
	a11y_structure_first_or_last: {
		code: 'a11y-structure',
		message: 'A11y: <figcaption> must be first or last child of <figure>'
	},
	a11y_mouse_events_have_key_events: /**
	 * @param {string} event
	 * @param {string} accompanied_by
	 */ (event, accompanied_by) => ({
		code: 'a11y-mouse-events-have-key-events',
		message: `A11y: on:${event} must be accompanied by on:${accompanied_by}`
	}),
	a11y_click_events_have_key_events: {
		code: 'a11y-click-events-have-key-events',
		message:
			'A11y: visible, non-interactive elements with an on:click event must be accompanied by an on:keydown, on:keyup, or on:keypress event.'
	},
	a11y_missing_content: /** @param {string} name */ (name) => ({
		code: 'a11y-missing-content',
		message: `A11y: <${name}> element should have child content`
	}),
	a11y_no_noninteractive_tabindex: {
		code: 'a11y-no-noninteractive-tabindex',
		message: 'A11y: noninteractive element cannot have nonnegative tabIndex value'
	},
	a11y_aria_activedescendant_has_tabindex: {
		code: 'a11y-aria-activedescendant-has-tabindex',
		message: 'A11y: Elements with attribute aria-activedescendant should have tabindex value'
	},
	redundant_event_modifier_for_touch: {
		code: 'redundant-event-modifier',
		message: "Touch event handlers that don't use the 'event' object are passive by default"
	},
	redundant_event_modifier_passive: {
		code: 'redundant-event-modifier',
		message: 'The passive modifier only works with wheel and touch events'
	},
	invalid_rest_eachblock_binding: /** @param {string} rest_element_name */ (rest_element_name) => ({
		code: 'invalid-rest-eachblock-binding',
		message: `The rest operator (...) will create a new object and binding '${rest_element_name}' with the original object will not work`
	}),
	avoid_mouse_events_on_document: {
		code: 'avoid-mouse-events-on-document',
		message:
			'Mouse enter/leave events on the document are not supported in all browsers and should be avoided'
	},
	illegal_attribute_character: {
		code: 'illegal-attribute-character',
		message:
			"Attributes should not contain ':' characters to prevent ambiguity with Svelte directives"
	}
};
