'use strict';
const path = require('path');
const resolveFrom = require('resolve-from');
const callerPath = require('caller-path');
const cache = require('./cache');
const {version} = require('./package.json');

const importJsx = (moduleId, options) => {
	if (typeof moduleId !== 'string') {
		throw new TypeError('Expected a string');
	}

	options = {
		pragma: 'h',
		pragmaFrag: 'Fragment',
		cache: true,
		...options
	};

	const modulePath = resolveFrom(path.dirname(callerPath()), moduleId);

	if (!options.cache) {
		delete require.cache[modulePath];
	}

	// If they used .jsx, and there's already a .jsx, then hook there
	// Otherwise, hook node's default .js
	const ext = path.extname(modulePath);
	const hookExt = require.extensions[ext] ? ext : '.js';

	const oldExtension = require.extensions[hookExt];

	require.extensions[hookExt] = module => {
		const oldCompile = module._compile;

		module._compile = source => {
			const result = cache({
				modulePath,
				options,
				source,
				version
			});

			module._compile = oldCompile;
			module._compile(result, modulePath);
		};

		require.extensions[hookExt] = oldExtension;
		oldExtension(module, modulePath);
	};

	const m = require(modulePath);
	require.extensions[hookExt] = oldExtension;

	if (!options.cache) {
		delete require.cache[modulePath];
	}

	return m;
};

module.exports = importJsx;
module.exports.default = importJsx;

module.exports.create = options => {
	return moduleId => importJsx(moduleId, options);
};
