import {
	tolerances,
} from "./constants";
import {
	getSharedDataEntry,
} from "./shared_data";

interface TmpPartition<T> {
	targetIds: T[];
	thickness: number;
	sheetCuttingProcessId: string | undefined;
	cuttingGasId?: string;
	sheetMaterialId?: string;
	sheetPriority?: number| undefined;
}

export interface SheetNestingPartitionTarget<T> {
	id: T;
	thickness: number;
	sheetCuttingProcessId?: string;
	sheetMaterialId?: string;
	laserSheetCuttingGasId?: string;
}

export interface SheetNestingPartition<T> {
	ids: T[];
	sheetMaterialId?: string | undefined;
}

/**
 * Partition targets into sub-sets where each sub-set could be nested on the same sheet
 *
 * Considered parameters are
 * 	- processId
 * 	- sheetMaterialId
 * 	- cuttingGasId
 * 	- sheet thickness
 *
 * Sheet filter is *not* considered yet.
 * Sheet dimensions are *not* considered yet.
 * Both are handled in DocumentGraphUpdater when computing the actual partitions based on potentially updated TwoDimRepresentations.
 */
export function computePotentialSheetNestingPartitions<T>(targets: readonly Readonly<SheetNestingPartitionTarget<T>>[]): SheetNestingPartition<T>[] {
	const sheetMergingEnabled = getSharedDataEntry("sheetMergingEnabled");
	const partitions: TmpPartition<T>[] = [];
	targets.forEach(target => {
		const sheetMaterialId = target.sheetMaterialId;
		const cuttingGasId = target.laserSheetCuttingGasId;

		if (sheetMaterialId === undefined || cuttingGasId === undefined) {
			partitions.push({
				targetIds: [ target.id ],
				thickness: target.thickness,
				sheetCuttingProcessId: target.sheetCuttingProcessId,
			});
			return;
		}

		const thickness = target.thickness;

		if (sheetMergingEnabled) {
			const partition = partitions.find(p => p.sheetCuttingProcessId === target.sheetCuttingProcessId
				&& p.sheetMaterialId !== undefined
				&& p.cuttingGasId !== undefined
				&& p.sheetMaterialId === sheetMaterialId
				&& p.cuttingGasId === cuttingGasId
				&& Math.abs(p.thickness - thickness) < tolerances.thickness);
			if (partition !== undefined) {
				partition.targetIds.push(target.id);
				return;
			}
		}

		partitions.push({
			targetIds: [ target.id ],
			thickness: target.thickness,
			sheetCuttingProcessId: target.sheetCuttingProcessId,
			sheetMaterialId: sheetMaterialId,
			cuttingGasId: cuttingGasId,
		});
	});

	return partitions.map(p => ({
		ids: p.targetIds,
		sheetMaterialId: p.sheetMaterialId,
	}));
}
