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

'use strict';

const pug = require( 'pug' );
const fs = require( 'fs' );
const upath = require( 'upath' );
const isNonEmptyArray = require( '../helpers/is-non-empty-array' );
const createFilterAttribs = require( '../helpers/create-filtering-data-attribs' );
const htmlsafe = require( '../helpers/html-safe' );
const splitLongname = require( '../helpers/split-longname' );
const extractLongname = require( '../helpers/extract-longname' );
const getApiInfoboxTooltip = require( '../helpers/get-api-infobox-tooltip' );
const capitalize = require( '../helpers/capitalize' );
const relative_url = require( 'hexo/dist/plugins/helper/relative_url' ); // eslint-disable-line camelcase

/**
 * Provides pug templates and adds various helpers to them.
 */
module.exports = class TemplateCollection {
	/**
	 * @param {String} templatePath Path to template files.
	 * @param {Boolean} pretty Whether to prettify template output or not.
	 */
	constructor( templatePath, {
		locals = {}
	} ) {
		/**
		 * @private
		 */
		this._path = templatePath;

		/**
		 * @private
		 */
		this._cache = {};

		/**
		 * @type {Array}
		 * @private
		 */
		this._helpers = {};

		/**
		 * @private
		 */
		this._locals = locals;
	}

	/**
	 * Returns compiled pug template. Templates are cached.
	 *
	 * @param templateName
	 * @returns {Function}
	 */
	getTemplate( templateName ) {
		const pathToFile = upath.resolve( this._path, `${ templateName }.pug` );

		if ( !( templateName in this._cache ) ) {
			this._cache[ templateName ] = pug.compile(
				fs.readFileSync( pathToFile, 'utf-8' ),
				{
					pretty: true,
					filename: upath.resolve( this._path, `${ templateName }.pug` ),
					basedir: this._path
				}
			);
		}

		return this._cache[ templateName ];
	}

	/**
	 * Renders a template with given data. Appends custom helpers to be used in template.
	 * @param templateName
	 * @param data
	 * @returns {String} Rendered html string.
	 */
	renderTemplate( templateName, data = {} ) {
		const template = this.getTemplate( templateName );

		if ( data.projectLocals && this._locals.projectLocals ) {
			Object.assign( this._locals.projectLocals, data.projectLocals );
		}

		data = Object.assign(
			data,
			{
				isNonEmptyArray,
				createFilterAttribs,
				htmlsafe,
				splitLongname,
				extractLongname,
				getApiInfoboxTooltip,
				capitalize,
				relative_url // eslint-disable-line camelcase
			},
			this._helpers,
			this._locals
		);

		return template( data );
	}

	/**
	 * Allows adding helpers to templates from outside.
	 * @param name
	 * @param fn
	 */
	addHelper( name, fn ) {
		this._helpers[ name ] = fn;
	}
};
