import {
	TableType,
	WorkStepType,
} from "qrc:/js/lib/generated/enum";
import {
	assert,
} from "qrc:/js/lib/utils";
import {
	getAssociatedSheetMaterialId,
	projectName,
} from "qrc:/js/lib/graph_utils";
import {
	getTable,
} from "qrc:/js/lib/table_utils";

export enum LstMaterial{
	mildSteel = "St37",
	stainlessSteel = "1.4301",
	alu = "AlMg3",
}

export function getLstMaterial(vertex: Vertex): LstMaterial {
	const materialId = getAssociatedSheetMaterialId(vertex);
	assert(materialId !== undefined, "Missing material for node");
	const sheetCuttingMaterialMapping = getTable(TableType.sheetCuttingMaterialMapping);
	const sheetCuttingMaterial = getTable(TableType.sheetCuttingMaterial);
	const mapping = sheetCuttingMaterialMapping.find(m => m.sheetMaterialId === materialId);
	assert(mapping !== undefined, "Missing sheet cutting material id");
	const material = sheetCuttingMaterial.find(m => m.identifier === mapping.sheetCuttingMaterialId);
	assert(material !== undefined, "Missing material id");

	const materialMap: Record<string, LstMaterial> = {
		1.4301: LstMaterial.stainlessSteel,
		1.0038: LstMaterial.mildSteel,
		AlMg3: LstMaterial.alu,
	};

	const lstMaterialKey = Object.keys(materialMap)
		.find(key => key === material.name);
	if (lstMaterialKey === undefined) {
		wsi4.util.warn("Couldn't identify lst material.  Using mild steel");
	}
	return lstMaterialKey === undefined ? LstMaterial.mildSteel : materialMap[lstMaterialKey]!;
}

interface ProcessDescription{
	// the process (e.g. MD5)
	process: string;
	// the process type (e.g. S0, B0, etc)
	processType: string;
	// true if a laser power warning should be shown (when the process does not exists for all laser powers)
	laserPowerWarning: boolean;
}

interface ProcessesPerThickness{
	// minimal thickness the processes exist
	minThickness: number;
	// maximal thickness the processes exist (exclusive)
	maxThickness: number;
	gas: string;
	material: LstMaterial;
	processes: ProcessDescription[];
}

const possibleProcesses: ProcessesPerThickness[] = [
	{
		minThickness: 1.0,
		maxThickness: 20.0,
		gas: "O2",
		material: LstMaterial.mildSteel,
		processes: [
			{
				process: "MD0",
				processType: "S0",
				laserPowerWarning: false,
			},
		],
	},
	{
		minThickness: 20.0,
		maxThickness: 25.1,
		gas: "O2",
		material: LstMaterial.mildSteel,
		processes: [
			{
				process: "MD0",
				processType: "S0",
				laserPowerWarning: true,
			},
		],
	},
	{
		minThickness: 1.0,
		maxThickness: 12.0,
		gas: "N2",
		material: LstMaterial.mildSteel,
		processes: [
			{
				process: "MD5",
				processType: "S0",
				laserPowerWarning: true,
			},
		],
	},
	{
		minThickness: 1.0,
		maxThickness: 8.0,
		gas: "N2",
		material: LstMaterial.mildSteel,
		processes: [
			{
				process: "MD0",
				processType: "S0",
				laserPowerWarning: false,
			},
		],
	},
	{
		minThickness: 1.0,
		maxThickness: 1.5,
		gas: "N2",
		material: LstMaterial.mildSteel,
		processes: [
			{
				process: "MD0",
				processType: "H0",
				laserPowerWarning: true,
			},
			{
				process: "MD4",
				processType: "S0",
				laserPowerWarning: true,
			},
		],
	},
	{
		minThickness: 1.5,
		maxThickness: 8.0,
		gas: "N2",
		material: LstMaterial.mildSteel,
		processes: [
			{
				process: "MD0",
				processType: "H0",
				laserPowerWarning: false,
			},
			{
				process: "MD4",
				processType: "S0",
				laserPowerWarning: false,
			},
		],
	},
	{
		minThickness: 8.0,
		maxThickness: 12.0,
		gas: "N2",
		material: LstMaterial.mildSteel,
		processes: [
			{
				process: "MD4",
				processType: "S0",
				laserPowerWarning: true,
			},
		],
	},
	{
		minThickness: 8.0,
		maxThickness: 20.0,
		gas: "N2",
		material: LstMaterial.mildSteel,
		processes: [
			{
				process: "MD0",
				processType: "S0",
				laserPowerWarning: true,
			},
			{
				process: "MD0",
				processType: "H0",
				laserPowerWarning: true,
			},
		],
	},
	{
		minThickness: 10.0,
		maxThickness: 25.1,
		gas: "O2",
		material: LstMaterial.mildSteel,
		processes: [
			{
				process: "MD0",
				processType: "B0",
				laserPowerWarning: false,
			},
		],
	},
	{
		minThickness: 10.0,
		maxThickness: 20.0,
		gas: "N2",
		material: LstMaterial.mildSteel,
		processes: [
			{
				process: "MD0",
				processType: "B0",
				laserPowerWarning: true,
			},
		],
	},
	{
		minThickness: 1.0,
		maxThickness: 25.1,
		gas: "O2",
		material: LstMaterial.alu,
		processes: [
			{
				process: "MD0",
				processType: "H0",
				laserPowerWarning: false,
			},
		],
	},
	{
		minThickness: 1.0,
		maxThickness: 25.1,
		gas: "N2",
		material: LstMaterial.alu,
		processes: [
			{
				process: "MD0",
				processType: "S0",
				laserPowerWarning: false,
			},
		],
	},
	{
		minThickness: 15.0,
		maxThickness: 25.1,
		gas: "N2",
		material: LstMaterial.alu,
		processes: [
			{
				process: "MD0",
				processType: "B0",
				laserPowerWarning: true,
			},
		],
	},
	{
		minThickness: 1.0,
		maxThickness: 6.0,
		gas: "N2",
		material: LstMaterial.stainlessSteel,
		processes: [
			{
				process: "MD4",
				processType: "S0",
				laserPowerWarning: false,
			},
		],
	},
	{
		minThickness: 10.0,
		maxThickness: 25.0,
		gas: "N2",
		material: LstMaterial.stainlessSteel,
		processes: [
			{
				process: "MD0",
				processType: "B0",
				laserPowerWarning: true,
			},
		],
	},
	{
		minThickness: 1.0,
		maxThickness: 12.0,
		gas: "N2",
		material: LstMaterial.stainlessSteel,
		processes: [
			{
				process: "MD5",
				processType: "S0",
				laserPowerWarning: true,
			},
		],
	},
	{
		minThickness: 1.0,
		maxThickness: 25.0,
		gas: "N2",
		material: LstMaterial.stainlessSteel,
		processes: [
			{
				process: "MD0",
				processType: "S0",
				laserPowerWarning: false,
			},
			{
				process: "MD0",
				processType: "H0",
				laserPowerWarning: false,
			},
		],
	},
];

interface LttIdentifier {
	id: string;
	laserPowerWarning: boolean;
}

export function getPossibleLstIdentifiers(sheetThickness: number, material: LstMaterial, gas: string): LttIdentifier[] {
	const materialPrefixMap: {[index in LstMaterial]: string} = {
		St37: "ST",
		1.4301: "SS",
		AlMg3: "AL",
	};
	const materialPrefix = materialPrefixMap[material];

	const thicknessString = (10.0 * sheetThickness).toFixed(0)
		.padStart(3, "0");

	assert(gas === "N2" || gas === "O2", "Wrong gas string");

	const processes = possibleProcesses.filter(p => p.gas === gas && p.material === material && sheetThickness >= p.minThickness && sheetThickness < p.maxThickness);
	if (processes.length === 0) {
		return [];
	}
	const ids: LttIdentifier[] = [];
	for (const p of processes) {
		for (const proc of p.processes) {
			ids.push({
				id: materialPrefix + thicknessString + proc.process + "-" + gas + proc.processType + "-30-2",
				laserPowerWarning: proc.laserPowerWarning,
			});
		}
	}
	assert(ids.every(id => id.id.length === 18), "Wrong length of lttIdentifier string");
	ids.sort((a, b) => a.id.localeCompare(b.id));
	return ids;
}

export function createLst(vertex: Vertex, lttIdentifier: string) : string {
	assert(wsi4.node.workStepType(vertex) === WorkStepType.sheet, "Missing twoDimRep");
	const twoDimRep = wsi4.node.twoDimRep(vertex);
	assert(twoDimRep !== undefined, "Missing twoDimRep");
	const jobName = projectName() === "" ? "HP" : projectName();
	const sheetThickness = wsi4.node.sheetThickness(vertex);
	assert(sheetThickness !== undefined, "Missing sheetThickness");
	const lstMaterial = getLstMaterial(vertex);
	return wsi4.cam.util.createLst(twoDimRep, jobName, sheetThickness, lstMaterial, lttIdentifier);
}
