import { describe, it, expect } from 'vitest';
import { encodeMap, parseMap, rleEncode, rleDecode } from '../mapFormat';
import type { TileMapData } from '../IsometricTileMap';

const sample: TileMapData = {
    width: 3,
    height: 2,
    tiles: [0, 0, 0, 1, 1, 2],
    blocked: [2],
    tall: { 3: { height: 1.5, ground: 0 } }
};

describe('RLE', () => {
    it('кодирует серии одинаковых id', () => {
        expect(rleEncode([0, 0, 0, 1, 1, 2])).toEqual([
            [0, 3],
            [1, 2],
            [2, 1]
        ]);
    });

    it('декодирует обратно', () => {
        expect(rleDecode([[0, 3], [1, 2], [2, 1]])).toEqual([0, 0, 0, 1, 1, 2]);
    });

    it('пустой массив', () => {
        expect(rleEncode([])).toEqual([]);
        expect(rleDecode([])).toEqual([]);
    });
});

describe('encodeMap/parseMap', () => {
    it('roundtrip с RLE сохраняет карту', () => {
        const file = encodeMap(sample);
        expect(file.format).toBe('rpg-map');
        expect(file.encoding).toBe('rle');
        const parsed = parseMap(JSON.parse(JSON.stringify(file)));
        expect(parsed).toEqual(sample);
    });

    it('roundtrip с raw', () => {
        const file = encodeMap(sample, 'raw');
        expect(file.tiles).toEqual([0, 0, 0, 1, 1, 2]);
        const parsed = parseMap(file);
        expect(parsed.tiles).toEqual(sample.tiles);
    });

    it('RLE реально сжимает однородную карту', () => {
        const big: TileMapData = { ...sample, width: 28, height: 28, tiles: new Array(784).fill(0) };
        const file = encodeMap(big);
        expect(JSON.stringify(file.tiles).length).toBeLessThan(20);
    });

    it('parseMap отвергает не-объект', () => {
        expect(() => parseMap('nope')).toThrow();
        expect(() => parseMap(null)).toThrow();
    });

    it('parseMap отвергает высоту в пикселях (tall.height > 16)', () => {
        expect(() => parseMap({ ...encodeMap(sample), tall: { 3: { height: 48, ground: 0 } } })).toThrow(/пикселях/);
    });

    it('parseMap отвергает чужой format/версию', () => {
        expect(() => parseMap({ ...encodeMap(sample), format: 'other' })).toThrow(/format/);
        expect(() => parseMap({ ...encodeMap(sample), version: 99 })).toThrow(/версия|версию|version/);
    });

    it('parseMap отвергает неверное число тайлов', () => {
        const file = encodeMap(sample, 'raw');
        (file as { tiles: number[] }).tiles = [0, 1, 2];
        expect(() => parseMap(file)).toThrow(/784|тайлов|6/);
    });
});