/** @license MIT | @cube-dev/ui-kit v0.147.0 | Cube Dev Team */
import { collides, getFirstCollision } from "./collision.js";
import { sortLayoutItemsByColRow, sortLayoutItemsByRowCol } from "./sort.js";
import { bottom, cloneLayout, cloneLayoutItem, getStatics } from "./layout.js";

//#region src/components/layout/Board/grid-core/compactors.ts
/**
* Compactor implementations.
*
* Vendored from react-grid-layout v2 (`src/core/compactors.ts`).
* See ./NOTICE.md for attribution and license.
*
* Compactors are pluggable strategies for removing gaps between grid items.
*/
/**
* Resolve a compaction collision by moving items.
*
* Before moving an item to a position, checks if that movement would cause
* collisions and recursively moves those items first.
*/
function resolveCompactionCollision(layout, item, moveToCoord, axis, hasStatics) {
	const sizeProp = axis === "x" ? "w" : "h";
	item[axis] += 1;
	const itemIndex = layout.findIndex((l) => l.i === item.i);
	const layoutHasStatics = hasStatics ?? getStatics(layout).length > 0;
	for (let i = itemIndex + 1; i < layout.length; i++) {
		const otherItem = layout[i];
		if (otherItem === void 0) continue;
		if (otherItem.static) continue;
		if (!layoutHasStatics && otherItem.y > item.y + item.h) break;
		if (collides(item, otherItem)) resolveCompactionCollision(layout, otherItem, moveToCoord + item[sizeProp], axis, layoutHasStatics);
	}
	item[axis] = moveToCoord;
}
/** Compact a single item vertically (move up). Mutates `l`. */
function compactItemVertical(compareWith, l, fullLayout, maxY) {
	l.x = Math.max(l.x, 0);
	l.y = Math.max(l.y, 0);
	l.y = Math.min(maxY, l.y);
	while (l.y > 0 && !getFirstCollision(compareWith, l)) l.y--;
	let collision;
	while ((collision = getFirstCollision(compareWith, l)) !== void 0) resolveCompactionCollision(fullLayout, l, collision.y + collision.h, "y");
	l.y = Math.max(l.y, 0);
	return l;
}
/** Compact a single item horizontally (move left). Mutates `l`. */
function compactItemHorizontal(compareWith, l, cols, fullLayout) {
	l.x = Math.max(l.x, 0);
	l.y = Math.max(l.y, 0);
	while (l.x > 0 && !getFirstCollision(compareWith, l)) l.x--;
	let collision;
	while ((collision = getFirstCollision(compareWith, l)) !== void 0) {
		resolveCompactionCollision(fullLayout, l, collision.x + collision.w, "x");
		if (l.x + l.w > cols) {
			l.x = cols - l.w;
			l.y++;
			while (l.x > 0 && !getFirstCollision(compareWith, l)) l.x--;
		}
	}
	l.x = Math.max(l.x, 0);
	return l;
}
/**
* Vertical compactor - moves items up to fill gaps. Default compaction mode.
*/
const verticalCompactor = {
	type: "vertical",
	allowOverlap: false,
	compact(layout, _cols) {
		const compareWith = getStatics(layout);
		let maxY = bottom(compareWith);
		const sorted = sortLayoutItemsByRowCol(layout);
		const out = new Array(layout.length);
		for (let i = 0; i < sorted.length; i++) {
			const sortedItem = sorted[i];
			if (sortedItem === void 0) continue;
			let l = cloneLayoutItem(sortedItem);
			if (!l.static) {
				l = compactItemVertical(compareWith, l, sorted, maxY);
				maxY = Math.max(maxY, l.y + l.h);
				compareWith.push(l);
			}
			const originalIndex = layout.indexOf(sortedItem);
			out[originalIndex] = l;
			l.moved = false;
		}
		return out;
	}
};
/**
* Horizontal compactor - moves items left to fill gaps.
*/
const horizontalCompactor = {
	type: "horizontal",
	allowOverlap: false,
	compact(layout, cols) {
		const compareWith = getStatics(layout);
		const sorted = sortLayoutItemsByColRow(layout);
		const out = new Array(layout.length);
		for (let i = 0; i < sorted.length; i++) {
			const sortedItem = sorted[i];
			if (sortedItem === void 0) continue;
			let l = cloneLayoutItem(sortedItem);
			if (!l.static) {
				l = compactItemHorizontal(compareWith, l, cols, sorted);
				compareWith.push(l);
			}
			const originalIndex = layout.indexOf(sortedItem);
			out[originalIndex] = l;
			l.moved = false;
		}
		return out;
	}
};
/**
* No compaction - items stay where placed (free-form layouts).
*/
const noCompactor = {
	type: null,
	allowOverlap: false,
	compact(layout, _cols) {
		return cloneLayout(layout);
	}
};
/** Vertical compactor that allows overlapping items. */
const verticalOverlapCompactor = {
	...verticalCompactor,
	allowOverlap: true,
	compact(layout, _cols) {
		return cloneLayout(layout);
	}
};
/** Horizontal compactor that allows overlapping items. */
const horizontalOverlapCompactor = {
	...horizontalCompactor,
	allowOverlap: true,
	compact(layout, _cols) {
		return cloneLayout(layout);
	}
};
/** No compaction, with overlapping allowed. */
const noOverlapCompactor = {
	...noCompactor,
	allowOverlap: true
};
/**
* Get a compactor by type (convenience for the string-based compactType API).
*/
function getCompactor(compactType, allowOverlap = false, preventCollision = false) {
	let baseCompactor;
	if (allowOverlap) if (compactType === "vertical") baseCompactor = verticalOverlapCompactor;
	else if (compactType === "horizontal") baseCompactor = horizontalOverlapCompactor;
	else baseCompactor = noOverlapCompactor;
	else if (compactType === "vertical") baseCompactor = verticalCompactor;
	else if (compactType === "horizontal") baseCompactor = horizontalCompactor;
	else baseCompactor = noCompactor;
	if (preventCollision) return {
		...baseCompactor,
		preventCollision
	};
	return baseCompactor;
}

//#endregion
export { getCompactor, horizontalCompactor, noCompactor, verticalCompactor };
//# sourceMappingURL=compactors.js.map