package jace.lawless;

import java.util.Arrays;

import jace.Emulator;
import jace.apple2e.RAM128k;
import jace.apple2e.VideoNTSC;
import jace.core.Computer;
import jace.core.PagedMemory;
import jace.core.Video;
import javafx.scene.image.WritableImage;

/**
 * Lawless-enhanced video output for readable text
 */
public class LawlessVideo extends VideoNTSC {

    private static RenderEngine activeEngine = RenderEngine.UNKNOWN;
    private boolean titleScreen = true;
    private final boolean[][] activeMask = new boolean[192][80];


    public enum RenderEngine {
        FULL_COLOR,
        FULL_TEXT(new int[]{
            2, 6, 78, 186
        }),
        _2D(new int[]{
            9, 8, 34, 17,
            44, 24, 76, 136,
            44, 143, 76, 184
        }),
        _3D(new int[]{
            9, 8, 34, 17,
            44, 24, 76, 136,
            44, 143, 76, 183,
            8, 172, 14, 182,}),
        MAP(new int[]{
            2, 6, 78, 11,
            2, 11, 4, 186,
            76, 11, 78, 186,
            2, 182, 78, 186,
            28, 3, 52, 6
        }),
        STORYBOOK(new int[]{
            0, 0, 39, 191,
            39, 130, 78, 191
        }),
        TITLE(new int[]{
            16, 154, 64, 190
        }),
        UNKNOWN;
        boolean[][] colorMask;

        RenderEngine(int[] mask) {
            this();
            for (int i = 0; i < mask.length; i += 4) {
                int x1 = mask[i],
                        y1 = mask[i + 1],
                        x2 = mask[i + 2],
                        y2 = mask[i + 3];
                for (int y = y1; y < y2; y++) {
                    for (int x = x1; x < x2; x++) {
                        colorMask[y][x] = false;
                    }
                }
            }
        }

        RenderEngine() {
            colorMask = new boolean[192][80];
            for (int y = 0; y < 192; y++) {
                colorMask[y] = new boolean[80];
                Arrays.fill(colorMask[y], true);
            }
        }
    }

    public LawlessVideo(Computer computer) {
        super(computer);
        this.vblankStart();
    }

    public void setEngine(RenderEngine e) {
        if (activeEngine != e) {
            titleScreen = false;
            activeEngine = e;
            for (int y=0; y < 192; y++) {
                System.arraycopy(activeEngine.colorMask[y], 0, activeMask[y], 0, 80);
            }
            
            Emulator.withComputer(c->c.onNextVBL(Video::forceRefresh));
            System.out.println("Detected engine: " + e.name());
        }
    }

    static public int[] divBy56 = new int[560];

    static {
        for (int i = 0; i < 560; i++) {
            divBy56[i] = i / 56;
        }
    }

    public int getSummary(int row) {
        PagedMemory mainMemory = ((RAM128k) computer.getMemory()).getMainMemory();
        int rowAddr = getCurrentWriter().getYOffset(row);
        int total = 0;
        for (int i = rowAddr + 4; i < rowAddr + 14; i++) {
            total += mainMemory.readByte(i) & 0x07f;
        }
        return total;
    }

    @Override
    public void hblankStart(WritableImage screen, int y, boolean isDirty) {
        int rowStart = getCurrentWriter().getYOffset(y);
        if (rowStart >= 0x02000) {
            boolean[] color = activeMask[y];
            if (titleScreen) {
                color = RenderEngine.FULL_COLOR.colorMask[y];
            }
            System.arraycopy(color, 0, colorActive, 0, 80);
        }
        super.hblankStart(screen, y, isDirty);
    }
}
