package school_project.Parsers;

import org.junit.jupiter.api.Test;
import school_project.Map;
import school_project.Piece;
import school_project.Vec2;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Arrays;

import static org.junit.jupiter.api.Assertions.*;

class BinaryParserTest {

    static byte[] file_data = {
            'S', 'M', 'S',
            6, 5, (byte) 0x31, (byte) 0xEC, (byte) 0xF3, (byte) 0xFC,
            4,
            (byte) 0x22, (byte) 0x70,
            (byte) 0x33, (byte) 0x99, (byte) 0x80,
            (byte) 0x32, (byte) 0x7C,
            (byte) 0x33, (byte) 0xDB, (byte) 0x80,
            'S', 'M', 'E'
    };

    @Test
    void getByteSizeForMap() {
        boolean[][] map_shape = {
                { true, true, true },
                { true, false, true },
                { true, true, true },

        };
        boolean[][] piece1_shape = {
                { true, true },
                { true, false },
                { true, true },

        };
        boolean[][] piece2_shape = {
                { true },
                { true },
                { true },

        };
        Map map = new Map(map_shape);
        Piece piece1 = new Piece(piece1_shape);
        Piece piece2 = new Piece(piece2_shape);

        map.addPiece(new Piece[]{piece1, piece2});
        piece2.setPosition(new Vec2(0, 2));


        assertEquals(15, BinaryParser.getByteSizeForMap(map, false));
        assertEquals(19, BinaryParser.getByteSizeForMap(map, true));
    }


    @Test
    void BuildByteFromMatrix(){
        byte[] map_data = Arrays.copyOfRange(file_data, 5, 9);
        boolean[][] map_shape = {
                {false, false, true, true, false, false},
                {false, true, true, true, true, false},
                {true, true, false, false, true, true},
                {true, true, false, false, true, true},
                {true, true, true, true, true, true},
        };
        assertArrayEquals(map_data, BinaryParser.BuildByteFromMatrix(map_shape));
    }

    @Test
    void BuildMatrixFromByte_map(){
        byte[] map_data = Arrays.copyOfRange(file_data, 5, 9);
        boolean[][] map_shape = {
                {false, false, true, true, false, false},
                {false, true, true, true, true, false},
                {true, true, false, false, true, true},
                {true, true, false, false, true, true},
                {true, true, true, true, true, true},
        };
        assertArrayEquals(map_shape, BinaryParser.BuildMatrixFromBytes(6, 5, map_data));
    }

    @Test
    void BuildMatrixFromByte_piece1(){
        byte[] piece1_data = Arrays.copyOfRange(file_data, 11, 12);
        boolean[][] piece1_shape = {
                {false, true},
                {true, true},
        };
        assertArrayEquals(piece1_shape, BinaryParser.BuildMatrixFromBytes(2, 2, piece1_data));
    }

    @Test
    void BuildMatrixFromByte_piece2(){
        byte[] piece2_data = Arrays.copyOfRange(file_data, 13, 15);
        boolean[][] piece2_shape = {
                {true, false, false},
                {true, true, false},
                {false, true, true},
        };
        assertArrayEquals(piece2_shape, BinaryParser.BuildMatrixFromBytes(3, 3, piece2_data));
    }

    @Test
    void BuildMatrixFromByte_piece3(){
        byte[] piece3_data = Arrays.copyOfRange(file_data, 16, 17);
        boolean[][] piece3_shape = {
                {false, true, true},
                {true, true, true},
        };
        assertArrayEquals(piece3_shape, BinaryParser.BuildMatrixFromBytes(3, 2, piece3_data));
    }

    @Test
    void BuildMatrixFromByte_piece4(){
        byte[] piece4_data = Arrays.copyOfRange(file_data, 18, 20);
        boolean[][] piece4_shape = {
                {true, true, false},
                {true, true, false},
                {true, true, true},
        };
        assertArrayEquals(piece4_shape, BinaryParser.BuildMatrixFromBytes(3, 3, piece4_data));
    }

    @Test
    void ExtractLevelData() throws IOException {
        boolean[][] expected_map_shape = {
                {false, false, true, true, false, false},
                {false, true, true, true, true, false},
                {true, true, false, false, true, true},
                {true, true, false, false, true, true},
                {true, true, true, true, true, true},
        };

        byte[] level_data = BinaryParser.ExtractLevelData(new ByteArrayInputStream(file_data));
        boolean[][] map = BinaryParser.ExtractMapFromLevelData(level_data);

        assertArrayEquals(expected_map_shape, map);
    }

    @Test
    void ExtractPiecesFronLevelDataTest() throws IOException {
        boolean[][] piece1_shape = {
                {false, true},
                {true, true},
        };
        boolean[][] piece2_shape = {
                {true, false, false},
                {true, true, false},
                {false, true, true},
        };
        boolean[][] piece3_shape = {
                {false, true, true},
                {true, true, true},
        };
        boolean[][] piece4_shape = {
                {true, true, false},
                {true, true, false},
                {true, true, true},
        };
        boolean[][][] pieces_shapes = {
                piece1_shape,
                piece2_shape,
                piece3_shape,
                piece4_shape
        };
        byte[] level_data = BinaryParser.ExtractLevelData(new ByteArrayInputStream(file_data));
        Piece[] pieces = BinaryParser.ExtractPiecesFromLevelData(level_data, false);

        for (int i = 0; i < pieces_shapes.length; i++) {
            assertArrayEquals(pieces_shapes[i], pieces[i].getShape());
        }
    }
}