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

import { BaseComponent } from './base-component';
import { html } from '../helpers/html-builder';

/**
 * IFrame component.
 */
export class IFrame extends BaseComponent {
	/**
	 * Creates a iframe component.
	 *
	 * @param element - The iframe wrapper DOM element
	 */
	constructor( element ) {
		super( {
			loaded: false
		} );

		this.elements = {
			wrapper: element
		};

		// Parse configuration from data attributes
		this.config = {
			autoResize: element.dataset.autoResize === 'true',
			width: element.dataset.width || null,
			height: element.dataset.height || null,
			src: element.dataset.src || null,
			content: element.dataset.content || null,
			...parseIframeAttributes( element )
		};
	}

	/**
	 * Attaches heading iframe functionality to all elements with js-heading-link class.
	 */
	static attach() {
		const iframes = document.querySelectorAll( '.c-iframe' );

		for ( const frame of iframes ) {
			frame.iframe = new IFrame( frame ).init();
		}
	}

	/**
	 * Initializes the iframe component.
	 */
	init() {
		this._createIframe();
		this._setupAutoResize();

		this.render();

		return this;
	}

	/**
	 * Renders the iframe component based on current state.
	 */
	render() {
		// Additional rendering logic if needed
	}

	/**
	 * Loads HTML content into iframe.
	 *
	 * @param content - HTML content to load
	 */
	setContent( content ) {
		const iframe = this.elements.iframe;
		const iframeDocument = iframe.contentDocument || iframe.contentWindow?.document;

		const wrappedHTML = `
			<!DOCTYPE html>
			${ content }
			${ this.config.autoResize ? `
			<script>
				const broadcastResize = () => {
					window.parent.postMessage( {
						type: 'iframeResized',
						height: Math.max( document.body.getBoundingClientRect().height, document.documentElement.offsetHeight ),
						wrapperId: '${ this.elements.wrapper.id }'
					}, '*' );
				};

				window.addEventListener( 'load', broadcastResize );
			</script>
			` : '' }
		`;

		if ( iframeDocument ) {
			iframeDocument.open();
			iframeDocument.write( wrappedHTML );
			iframeDocument.close();
		}
	}

	/**
	 * Creates and injects iframe into the wrapper.
	 */
	_createIframe() {
		const { wrapper } = this.elements;
		const { width, height, src, autoResize, ...iframeAttrs } = this.config;

		const iframe = html.iframe( {
			class: 'c-iframe__frame b-iframe',
			...( src && { src } ),
			...( width && { style: `width: ${ width }` } ),
			...( height && !autoResize && { style: `height: ${ height }` } ),
			...iframeAttrs
		} );

		wrapper.appendChild( iframe );
		this.elements.iframe = iframe;

		// Load content if provided
		if ( this.config.content ) {
			this.setContent( this.config.content );
		}
	}

	/**
	 * Sets up auto-resize functionality.
	 */
	_setupAutoResize() {
		if ( !this.config.autoResize ) {
			return;
		}

		// Add message listener for this instance
		window.addEventListener( 'message', event => {
			if ( event.data && event.data.type === 'iframeResized' && event.source === this.elements.iframe?.contentWindow ) {
				this.elements.iframe.style.height = ( event.data.height + 5 ) + 'px';
			}
		} );
	}
}

/**
 * Parses iframe attributes from data attributes.
 *
 * @param element - The wrapper element
 * @returns Object with iframe attributes
 */
function parseIframeAttributes( element ) {
	return Array
		.from( element.attributes )
		.filter( attr => attr.name.startsWith( 'data-iframe-' ) )
		.reduce( ( attributes, attr ) => {
			const attrName = attr.name.replace( 'data-iframe-', '' );
			attributes[ attrName ] = attr.value;
			return attributes;
		}, Object.create( {} ) );
}
