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

'use strict';

const CODE_SWITCHER_REGEXP = /<code-switcher[^>]*>([\s\S]*?)<\/code-switcher>/g;
const CODE_SWITCHER_TYPE_REGEXP = /<code-switcher\s*(\w*)[^>]*>/;
const CODEBLOCK_REGEXP_STRING = /```(\S+)?(\n[\s\S]*?)```/g;

const textEncoder = new TextEncoder();

/**
 * Replaces the `<code-switcher>` element with the HTML structure. E.g.:
 *
 *      <code-switcher>
 *      ```js
 * 		Content
 *      ```
 *      </code-switcher>
 *
 * will be transformed into:
 *		<div class="code-switcher selfhosted">
 *			<div class="code-switcher__toolbar">
 *				<button class="code-switcher__button code-switcher__button--active">Self-hosted (NPM)</button>
 *				<button class="code-switcher__button">Cloud (CDN)</button>
 *			</div>
 *      	<div class="code-toolbar">
 * 				<pre>
 * 					<code>Content</code>
 *				</pre>
 *				<div class="toolbar">...</div>
 *      	</div>
 * 		</div>
 *
 *
 * @protected
 * @param {Object} page
 * @param {Object} hexo
 * @return {Object} page
 */
module.exports = function transformCodeSwitcher( page, hexo ) {
	page.content = processCodeSwitcher( page.content, hexo );

	return page;
};

function processCodeSwitcher( content, hexo ) {
	return content.replace( CODE_SWITCHER_REGEXP, ( match, content ) => {
		const classSwitcher = 'code-switcher';
		const type = CODE_SWITCHER_TYPE_REGEXP.exec( match )[ 1 ];
		const classSnippet = type ? type : 'selfhosted';

		// 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 }` );
		}

		content = lines.map( line => line.replace( pattern, '' ) ).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 ) => {
			// Angle brackets were missing after encoding. And we need them, for example, in strings like '<YOUR_LICENSE_KEY>'.
			// That's why we replace them with HTML entities.
			const encodedContent = textEncoder.encode( content.replace( /</g, '&lt;' ).replace( />/g, '&gt;' ) );

			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="${ classSwitcher } ${ classSnippet }"><div class="code-switcher__toolbar"></div>${ markdownOutput }</div>`;
	} );
}
