/**
 * @license Copyright (c) 2017-2025, CKSource Holding sp. z o.o. All rights reserved.
 * For licensing, see LICENSE.md.
 */

import { html } from '../helpers/html-builder';
import { cx } from '../helpers/classnames';
import { randomId } from '../helpers/random-id';

/**
 * A web component that renders an SVG icon. This is equivalent to the `svg-icon` Pug mixin.
 *
 * In order to load icon into spritesheet, you need to use the `preload-spritesheet-svg` mixin.
 *
 * @example
 * // Basic usage
 * <svg-icon icon="github"></svg-icon>
 *
 * // With additional class
 * <svg-icon icon="github" class="custom-icon-class"></svg-icon>
 *
 * // With size
 * <svg-icon icon="github" size="lg"></svg-icon>
 *
 * // With title for accessibility (omit for decorative icons)
 * <svg-icon icon="github" title="GitHub"></svg-icon>
 */
class SvgIcon extends HTMLElement {
	static get observedAttributes() {
		return [ 'icon', 'size', 'class', 'title', 'aria-hidden' ];
	}

	connectedCallback() {
		this.render();
	}

	attributeChangedCallback() {
		this.render();
	}

	render() {
		const icon = this.getAttribute( 'icon' );
		const size = this.getAttribute( 'size' );
		const title = this.getAttribute( 'title' );
		const ariaHidden = this.hasAttribute( 'aria-hidden' ) ?
			this.getAttribute( 'aria-hidden' ) === 'true' :
			!title;

		if ( !icon ) {
			console.error( 'Icon name is required for <svg-icon> element' );
			return;
		}

		const svgElement = createSvgIcon( {
			file: `icons-${ icon }`,
			className: cx(
				'c-icon',
				`c-icon--${ icon }`,
				{ [ `u-text--${ size }` ]: !!size }
			),
			viewBox: '0 0 36 36',
			ariaHidden: ariaHidden ? 'true' : 'false',
			title: title && !ariaHidden ? title : null
		} );

		this.innerHTML = '';
		this.appendChild( svgElement );
	}
}

customElements.define( 'svg-icon', SvgIcon );

/**
 * Creates an SVG element with an icon from a spritesheet.
 */
function createSvgIcon( options ) {
	const {
		file,
		className,
		style,
		width,
		height,
		title,
		viewBox,
		ariaHidden
	} = options;

	if ( !file ) {
		return null;
	}

	if ( !viewBox ) {
		throw new Error( 'The viewBox attribute is required for the SVG element.' );
	}

	const iconId = file.replace( /\//g, '-' );
	const titleId = title ? randomId( 'svg-icon-title' ) : null;

	const svgElement = html.svg(
		{
			role: 'img',
			...( className && { class: className } ),
			...( style && { style } ),
			...( width && { width } ),
			...( height && { height } ),
			...( title && { 'aria-labelledby': titleId } ),
			...( ariaHidden && { 'aria-hidden': ariaHidden } ),
			...( viewBox && { viewBox } )
		},
		[
			title && html.title( { id: titleId }, title ),
			html.use( { href: `#${ iconId }` } )
		].filter( Boolean )
	);

	return svgElement;
}
