import { dirname, relative } from 'path';
import * as yargs from 'yargs';
const { wrapCallSite } = require('source-map-support');

/* eslint-disable no-console */

const resolveLine = (lineNumber: number, columnNumber: number, filePath: string) => {
	// Note: This is an undocumented function provided by source-map-support. It
	// may change in the future:
	const frame = wrapCallSite({
		getFileName: () => filePath,
		isEval: ()=>false,
		isNative: ()=>false,
		getLineNumber: ()=>lineNumber,
		getColumnNumber: ()=>columnNumber,
	});

	const baseDir = dirname(dirname(dirname(__dirname)));
	const relativeFilePath = relative(baseDir, frame.getFileName());
	return `${relativeFilePath}:${frame.getLineNumber()}`;
};

const resolvePosition = (position: string, sourceMap: string) => {
	const match = /^(\d{1,10}):(\d{1,10})$/.exec(position.trim());
	if (!match) {
		throw new Error('Invalid format. Expected line:col');
	}

	const lineNumber = Number(match[1]);
	const columnNumber = Number(match[2]);
	return resolveLine(lineNumber, columnNumber, sourceMap);
};

void yargs
	.usage('$0 [args]')
	.command(
		'$0 <position>',
		'Resolves a position based on a source map. If resolving a position in a specific error message, be sure to use the source map generated by "yarn bundle" from that specific commit.',
		(yargs) => {
			return yargs.options({
				'position': { type: 'string', help: 'A line:col position (e.g. 123:4567)' },
				'sourcemap': {
					type: 'string',
					default: './main-html.bundle.js',
					help: 'The path to the source map. This source map should be a source map compiled from the commit/release that created the error.',
				},
			});
		},
		async (args) => {
			console.log(await resolvePosition(args.position, args.sourcemap));
			process.exit(0);
		},
	)
	.help()
	.argv;
