/**
 * External dependencies
 */
const escapeStringRegexp = require( 'escape-string-regexp' );

/**
 * Webpack plugin for handling specific template tags in Webpack configuration
 * values like those supported in the base Webpack functionality (e.g. `name`).
 *
 * @see webpack.TemplatedPathPlugin
 */
class CustomTemplatedPathPlugin {
	/**
	 * CustomTemplatedPathPlugin constructor. Initializes handlers as a tuple
	 * set of RegExp, handler, where the regular expression is used in matching
	 * a Webpack asset path.
	 *
	 * @param {Object.<string,Function>} handlers Object keyed by tag to match,
	 *                                            with function value returning
	 *                                            replacement string.
	 */
	constructor( handlers ) {
		this.handlers = [];

		for ( const [ key, handler ] of Object.entries( handlers ) ) {
			const regexp = new RegExp(
				`\\[${ escapeStringRegexp( key ) }\\]`,
				'gi'
			);
			this.handlers.push( [ regexp, handler ] );
		}
	}

	/**
	 * Webpack plugin application logic.
	 *
	 * @param {Object} compiler Webpack compiler
	 */
	apply( compiler ) {
		compiler.hooks.compilation.tap(
			'CustomTemplatedPathPlugin',
			( compilation ) => {
				compilation.hooks.assetPath.tap(
					'CustomTemplatedPathPlugin',
					( path, data ) => {
						for ( let i = 0; i < this.handlers.length; i++ ) {
							const [ regexp, handler ] = this.handlers[ i ];
							if ( regexp.test( path ) ) {
								path = path.replace(
									regexp,
									handler( path, data )
								);
							}
						}

						return path;
					}
				);
			}
		);
	}
}

module.exports = CustomTemplatedPathPlugin;
