/**
 * Изометрия 2:1 (классический «ромб»).
 *
 * Сетка — целочисленные координаты тайлов (tx, ty).
 * Экран — виртуальные пиксели. Тайл рисуется ромбом шириной tileW и высотой tileH (2:1).
 *
 * Формулы:
 *   screenX = (tx - ty) * (tileW / 2)
 *   screenY = (tx + ty) * (tileH / 2)
 * Обратная:
 *   tx = (screenX / (tileW/2) + screenY / (tileH/2)) / 2
 *   ty = (screenY / (tileH/2) - screenX / (tileW/2)) / 2
 */

export interface IsoLayout {
    /** Ширина ромба тайла (пиксели, чётное). */
    tileW: number;
    /** Высота ромба тайла (пиксели, tileW / 2). */
    tileH: number;
    /** Экранные координаты верхнего левого угла нулевого тайла. */
    originX: number;
    originY: number;
}

/** Стандартный тайл 32x16. */
export const DEFAULT_ISO: IsoLayout = { tileW: 32, tileH: 16, originX: 0, originY: 0 };

export function isoToScreen(tx: number, ty: number, iso: IsoLayout = DEFAULT_ISO): { x: number; y: number } {
    return {
        x: Math.round((tx - ty) * (iso.tileW / 2) + iso.originX),
        y: Math.round((tx + ty) * (iso.tileH / 2) + iso.originY)
    };
}

export function screenToIso(sx: number, sy: number, iso: IsoLayout = DEFAULT_ISO): { x: number; y: number } {
    const halfW = iso.tileW / 2;
    const halfH = iso.tileH / 2;
    const dx = (sx - iso.originX) / halfW;
    const dy = (sy - iso.originY) / halfH;
    return { x: Math.floor((dx + dy) / 2), y: Math.floor((dy - dx) / 2) };
}

/**
 * Точное попадание внутрь ромба тайла (floor может дать соседний тайл на границе).
 * Возвращает координаты тайла, ромб которого содержит точку, или null.
 */
export function screenToIsoExact(
    sx: number,
    sy: number,
    mapW: number,
    mapH: number,
    iso: IsoLayout = DEFAULT_ISO
): { x: number; y: number } | null {
    const cand = screenToIso(sx, sy, iso);
    for (let dy = 0; dy <= 1; dy++) {
        for (let dx = 0; dx <= 1; dx++) {
            const tx = cand.x + dx;
            const ty = cand.y + dy;
            const c = isoToScreen(tx, ty, iso);
            const rx = sx - c.x;
            const ry = sy - c.y;
            // Ромб: |x/halfW| + |y/halfH| <= 1
            if (Math.abs(rx) / (iso.tileW / 2) + Math.abs(ry) / (iso.tileH / 2) <= 1) {
                if (tx >= 0 && ty >= 0 && tx < mapW && ty < mapH) {
                    return { x: tx, y: ty };
                }
                return null;
            }
        }
    }
    return null;
}