/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
"use strict";

const Generator = require("../Generator");
const Template = require("../Template");
const WebAssemblyUtils = require("./WebAssemblyUtils");
const { RawSource } = require("webpack-sources");

const { editWithAST, addWithAST } = require("@webassemblyjs/wasm-edit");
const { decode } = require("@webassemblyjs/wasm-parser");
const t = require("@webassemblyjs/ast");
const {
	moduleContextFromModuleAST
} = require("@webassemblyjs/helper-module-context");

const WebAssemblyExportImportedDependency = require("../dependencies/WebAssemblyExportImportedDependency");

/** @typedef {import("../Module")} Module */
/** @typedef {import("./WebAssemblyUtils").UsedWasmDependency} UsedWasmDependency */
/** @typedef {import("../NormalModule")} NormalModule */
/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../Dependency").DependencyTemplate} DependencyTemplate */

/**
 * @typedef {(ArrayBuffer) => ArrayBuffer} ArrayBufferTransform
 */

/**
 * @template T
 * @param {Function[]} fns transforms
 * @returns {Function} composed transform
 */
const compose = (...fns) => {
	return fns.reduce(
		(prevFn, nextFn) => {
			return value => nextFn(prevFn(value));
		},
		value => value
	);
};

// TODO replace with @callback

/**
 * Removes the start instruction
 *
 * @param {Object} state unused state
 * @returns {ArrayBufferTransform} transform
 */
const removeStartFunc = state => bin => {
	return editWithAST(state.ast, bin, {
		Start(path) {
			path.remove();
		}
	});
};

/**
 * Get imported globals
 *
 * @param {Object} ast Module's AST
 * @returns {Array<t.ModuleImport>} - nodes
 */
const getImportedGlobals = ast => {
	const importedGlobals = [];

	t.traverse(ast, {
		ModuleImport({ node }) {
			if (t.isGlobalType(node.descr)) {
				importedGlobals.push(node);
			}
		}
	});

	return importedGlobals;
};

/**
 * Get the count for imported func
 *
 * @param {Object} ast Module's AST
 * @returns {Number} - count
 */
const getCountImportedFunc = ast => {
	let count = 0;

	t.traverse(ast, {
		ModuleImport({ node }) {
			if (t.isFuncImportDescr(node.descr)) {
				count++;
			}
		}
	});

	return count;
};

/**
 * Get next type index
 *
 * @param {Object} ast Module's AST
 * @returns {t.Index} - index
 */
const getNextTypeIndex = ast => {
	const typeSectionMetadata = t.getSectionMetadata(ast, "type");

	if (typeSectionMetadata === undefined) {
		return t.indexLiteral(0);
	}

	return t.indexLiteral(typeSectionMetadata.vectorOfSize.value);
};

/**
 * Get next func index
 *
 * The Func section metadata provide informations for implemented funcs
 * in order to have the correct index we shift the index by number of external
 * functions.
 *
 * @param {Object} ast Module's AST
 * @param {Number} countImportedFunc number of imported funcs
 * @returns {t.Index} - index
 */
const getNextFuncIndex = (ast, countImportedFunc) => {
	const funcSectionMetadata = t.getSectionMetadata(ast, "func");

	if (funcSectionMetadata === undefined) {
		return t.indexLiteral(0 + countImportedFunc);
	}

	const vectorOfSize = funcSectionMetadata.vectorOfSize.value;

	return t.indexLiteral(vectorOfSize + countImportedFunc);
};

/**
 * Creates an init instruction for a global type
 * @param {t.GlobalType} globalType the global type
 * @returns {t.Instruction} init expression
 */
const createDefaultInitForGlobal = globalType => {
	if (globalType.valtype[0] === "i") {
		// create NumberLiteral global initializer
		return t.objectInstruction("const", globalType.valtype, [
			t.numberLiteralFromRaw(66)
		]);
	} else if (globalType.valtype[0] === "f") {
		// create FloatLiteral global initializer
		return t.objectInstruction("const", globalType.valtype, [
			t.floatLiteral(66, false, false, "66")
		]);
	} else {
		throw new Error("unknown type: " + globalType.valtype);
	}
};

/**
 * Rewrite the import globals:
 * - removes the ModuleImport instruction
 * - injects at the same offset a mutable global of the same type
 *
 * Since the imported globals are before the other global declarations, our
 * indices will be preserved.
 *
 * Note that globals will become mutable.
 *
 * @param {Object} state unused state
 * @returns {ArrayBufferTransform} transform
 */
const rewriteImportedGlobals = state => bin => {
	const additionalInitCode = state.additionalInitCode;
	const newGlobals = [];

	bin = editWithAST(state.ast, bin, {
		ModuleImport(path) {
			if (t.isGlobalType(path.node.descr)) {
				const globalType = path.node.descr;

				globalType.mutability = "var";

				const init = [
					createDefaultInitForGlobal(globalType),
					t.instruction("end")
				];

				newGlobals.push(t.global(globalType, init));

				path.remove();
			}
		},

		// in order to preserve non-imported global's order we need to re-inject
		// those as well
		Global(path) {
			const { node } = path;
			const [init] = node.init;

			if (init.id === "get_global") {
				node.globalType.mutability = "var";

				const initialGlobalidx = init.args[0];

				node.init = [
					createDefaultInitForGlobal(node.globalType),
					t.instruction("end")
				];

				additionalInitCode.push(
					/**
					 * get_global in global initializer only works for imported globals.
					 * They have the same indices as the init params, so use the
					 * same index.
					 */
					t.instruction("get_local", [initialGlobalidx]),
					t.instruction("set_global", [t.indexLiteral(newGlobals.length)])
				);
			}

			newGlobals.push(node);

			path.remove();
		}
	});

	// Add global declaration instructions
	return addWithAST(state.ast, bin, newGlobals);
};

/**
 * Rewrite the export names
 * @param {Object} state state
 * @param {Object} state.ast Module's ast
 * @param {Module} state.module Module
 * @param {Set<string>} state.externalExports Module
 * @returns {ArrayBufferTransform} transform
 */
const rewriteExportNames = ({ ast, module, externalExports }) => bin => {
	return editWithAST(ast, bin, {
		ModuleExport(path) {
			const isExternal = externalExports.has(path.node.name);
			if (isExternal) {
				path.remove();
				return;
			}
			const usedName = module.isUsed(path.node.name);
			if (!usedName) {
				path.remove();
				return;
			}
			path.node.name = usedName;
		}
	});
};

/**
 * Mangle import names and modules
 * @param {Object} state state
 * @param {Object} state.ast Module's ast
 * @param {Map<string, UsedWasmDependency>} state.usedDependencyMap mappings to mangle names
 * @returns {ArrayBufferTransform} transform
 */
const rewriteImports = ({ ast, usedDependencyMap }) => bin => {
	return editWithAST(ast, bin, {
		ModuleImport(path) {
			const result = usedDependencyMap.get(
				path.node.module + ":" + path.node.name
			);

			if (result !== undefined) {
				path.node.module = result.module;
				path.node.name = result.name;
			}
		}
	});
};

/**
 * Add an init function.
 *
 * The init function fills the globals given input arguments.
 *
 * @param {Object} state transformation state
 * @param {Object} state.ast Module's ast
 * @param {t.Identifier} state.initFuncId identifier of the init function
 * @param {t.Index} state.startAtFuncOffset index of the start function
 * @param {t.ModuleImport[]} state.importedGlobals list of imported globals
 * @param {t.Instruction[]} state.additionalInitCode list of addition instructions for the init function
 * @param {t.Index} state.nextFuncIndex index of the next function
 * @param {t.Index} state.nextTypeIndex index of the next type
 * @returns {ArrayBufferTransform} transform
 */
const addInitFunction = ({
	ast,
	initFuncId,
	startAtFuncOffset,
	importedGlobals,
	additionalInitCode,
	nextFuncIndex,
	nextTypeIndex
}) => bin => {
	const funcParams = importedGlobals.map(importedGlobal => {
		// used for debugging
		const id = t.identifier(`${importedGlobal.module}.${importedGlobal.name}`);

		return t.funcParam(importedGlobal.descr.valtype, id);
	});

	const funcBody = importedGlobals.reduce((acc, importedGlobal, index) => {
		const args = [t.indexLiteral(index)];
		const body = [
			t.instruction("get_local", args),
			t.instruction("set_global", args)
		];

		return [...acc, ...body];
	}, []);

	if (typeof startAtFuncOffset === "number") {
		funcBody.push(t.callInstruction(t.numberLiteralFromRaw(startAtFuncOffset)));
	}

	for (const instr of additionalInitCode) {
		funcBody.push(instr);
	}

	funcBody.push(t.instruction("end"));

	const funcResults = [];

	// Code section
	const funcSignature = t.signature(funcParams, funcResults);
	const func = t.func(initFuncId, funcSignature, funcBody);

	// Type section
	const functype = t.typeInstruction(undefined, funcSignature);

	// Func section
	const funcindex = t.indexInFuncSection(nextTypeIndex);

	// Export section
	const moduleExport = t.moduleExport(
		initFuncId.value,
		t.moduleExportDescr("Func", nextFuncIndex)
	);

	return addWithAST(ast, bin, [func, moduleExport, funcindex, functype]);
};

/**
 * Extract mangle mappings from module
 * @param {Module} module current module
 * @param {boolean} mangle mangle imports
 * @returns {Map<string, UsedWasmDependency>} mappings to mangled names
 */
const getUsedDependencyMap = (module, mangle) => {
	/** @type {Map<string, UsedWasmDependency>} */
	const map = new Map();
	for (const usedDep of WebAssemblyUtils.getUsedDependencies(module, mangle)) {
		const dep = usedDep.dependency;
		const request = dep.request;
		const exportName = dep.name;
		map.set(request + ":" + exportName, usedDep);
	}
	return map;
};

class WebAssemblyGenerator extends Generator {
	constructor(options) {
		super();
		this.options = options;
	}

	/**
	 * @param {NormalModule} module module for which the code should be generated
	 * @param {Map<Function, DependencyTemplate>} dependencyTemplates mapping from dependencies to templates
	 * @param {RuntimeTemplate} runtimeTemplate the runtime template
	 * @param {string} type which kind of code should be generated
	 * @returns {Source} generated code
	 */
	generate(module, dependencyTemplates, runtimeTemplate, type) {
		let bin = module.originalSource().source();

		const initFuncId = t.identifier(
			Array.isArray(module.usedExports)
				? Template.numberToIdentifer(module.usedExports.length)
				: "__webpack_init__"
		);

		// parse it
		const ast = decode(bin, {
			ignoreDataSection: true,
			ignoreCodeSection: true,
			ignoreCustomNameSection: true
		});

		const moduleContext = moduleContextFromModuleAST(ast.body[0]);

		const importedGlobals = getImportedGlobals(ast);
		const countImportedFunc = getCountImportedFunc(ast);
		const startAtFuncOffset = moduleContext.getStart();
		const nextFuncIndex = getNextFuncIndex(ast, countImportedFunc);
		const nextTypeIndex = getNextTypeIndex(ast);

		const usedDependencyMap = getUsedDependencyMap(
			module,
			this.options.mangleImports
		);
		const externalExports = new Set(
			module.dependencies
				.filter(d => d instanceof WebAssemblyExportImportedDependency)
				.map(d => {
					const wasmDep = /** @type {WebAssemblyExportImportedDependency} */ (d);
					return wasmDep.exportName;
				})
		);

		/** @type {t.Instruction[]} */
		const additionalInitCode = [];

		const transform = compose(
			rewriteExportNames({
				ast,
				module,
				externalExports
			}),

			removeStartFunc({ ast }),

			rewriteImportedGlobals({ ast, additionalInitCode }),

			rewriteImports({
				ast,
				usedDependencyMap
			}),

			addInitFunction({
				ast,
				initFuncId,
				importedGlobals,
				additionalInitCode,
				startAtFuncOffset,
				nextFuncIndex,
				nextTypeIndex
			})
		);

		const newBin = transform(bin);

		return new RawSource(newBin);
	}
}

module.exports = WebAssemblyGenerator;
