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

'use strict';

const INFO_BOX_REGEXP = /<info-box[^>]*>([\s\S]*?)<\/info-box>/g;
const INFO_BOX_TYPE_REGEXP = /<info-box\s*(\w*)[^>]*>/;
const CODEBLOCK_REGEXP_STRING = /```(\S+)?(\n[\s\S]*?)```/g;

const textEncoder = new TextEncoder();

/**
 * Replaces the `<info-box>` element with the HTML `div` element. E.g.:
 *
 *      <info-box type>
 *          Content
 *      </info-box>
 *
 * will be transformed into:
 *
 *      <div class="info-box notice">
 *          Content
 *      </div>
 *
 * See #896.
 *
 * @protected
 * @param {Object} page
 * @param {Object} hexo
 * @return {Boolean}
 */
module.exports = function transformInfoBox( page, hexo ) {
	page.content = processInfobox( page.content, hexo );

	return page;
};

function processInfobox( content, hexo ) {
	return content.replace( INFO_BOX_REGEXP, ( match, content ) => {
		const typeMatch = INFO_BOX_TYPE_REGEXP.exec( match );
		const type = typeMatch[ 1 ];
		const classStr = type ? `info-box notice notice__${ type }` : 'info-box notice';

		// Remove unwanted indentation.
		const lines = content.split( /\n/ );
		const indentation = lines.length > 1 ? lines[ 1 ].match( /^\s*/ )[ 0 ] : '';

		let pattern;

		// When using spaces as indentation, some editors may mix them with tabs.
		// In such case, let's try to remove tabs as well. 4 spaces are treat as a single tab character.
		if ( indentation[ 0 ] === ' ' ) {
			pattern = new RegExp( `^${ indentation }|${ '\\t'.repeat( Math.ceil( indentation.length / 4 ) ) }` );
		} else {
			pattern = new RegExp( `^${ indentation }` );
		}

		const trimmedLines = lines.map( line => line.replace( pattern, '' ) );
		content = trimmedLines.join( '\n' );

		// Remove first linebreak and last linebreak.
		content = content.replace( /^\n/, '' );
		content = content.replace( /\n$/, '' );

		// Encoding codeblocks inside infobox into UTF-8. See #1122.
		content = content.replace( CODEBLOCK_REGEXP_STRING, ( match, language, content ) => {
			const encodedContent = textEncoder.encode( content );

			return language ?
				`<pre class="highlight"><code class="${ language }">utf8_encoded_content:${ encodedContent }</code></pre>` :
				`<pre class="highlight"><code>utf8_encoded_content:${ encodedContent }</code></pre>`;
		} );

		let markdownOutput = hexo.render.renderSync( { text: content, engine: 'markdown' } );
		markdownOutput = markdownOutput.replace( /<\/p>\n/g, '</p>' );
		markdownOutput = markdownOutput.replace( /\n<p>/g, '<p>' );

		return `<div class="${ classStr }">${ markdownOutput }</div>`;
	} );
}
