import {
	assert,
	bbDimensionX,
	bbDimensionY,
} from "./utils";

interface DefaultLayeredSelection {
	cuttingLds: number[];
	engravingLds: number[];
}

export function getDefaultLayeredSelection(layered: Layered): DefaultLayeredSelection {
	const layers = wsi4.geo.util.layers(layered);
	const biggestIopLayer = (() => {
		let biggestIop: InnerOuterPolygon | undefined = undefined;
		let biggestVolume = 0;
		let des = -1;
		for (const layer of layers) {
			// can't use flatMap
			const segments = wsi4.geo.util.layerPaths(layered, layer.descriptor).reduce((s: Segment[], path) => [
				...s,
				...path,
			], []);
			const iop = wsi4.geo.util.createIop(segments);
			if (iop === undefined) {
				continue;
			}
			const b = wsi4.geo.util.boundingBox2d(iop);
			const v = bbDimensionX(b) * bbDimensionY(b);
			if (v !== 0 && v > biggestVolume) {
				assert(!wsi4.geo.util.isLayerEmpty(layered, layer.descriptor), "Empty layer the biggest layer iop");
				biggestIop = iop;
				biggestVolume = v;
				des = layer.descriptor;
			}
		}
		if (biggestIop === undefined) {
			return undefined;
		}
		return {
			iop: biggestIop,
			des: des,
		};

	})();
	if (biggestIopLayer === undefined) {
		return {
			cuttingLds: [],
			engravingLds: [],
		};
	}
	return layers.reduce((res: DefaultLayeredSelection, layer: Layer) => {
		if (layer.descriptor === biggestIopLayer.des) {
			res.cuttingLds.push(layer.descriptor);
		} else if (wsi4.geo.util.isLayerEmpty(layered, layer.descriptor)) {
			// empty layer should not be in default selection
			return res;
		} else {
			const layerPaths = wsi4.geo.util.layerPaths(layered, layer.descriptor);
			if (layerPaths.every(path => wsi4.geo.util.partiallyContained(path, wsi4.geo.util.outerPolygon(biggestIopLayer.iop)))) {
				res.engravingLds.push(layer.descriptor);
			}
		}
		return res;
	}, {
		cuttingLds: [],
		engravingLds: [],
	});
}
