#include <lcd.h>
#include <ppu.h>
#include <dma.h>

static lcd_context ctx;

static unsigned long colors_default[4] = {0xFFFFFFFF, 0xFFAAAAAA, 0xFF555555, 0xFF000000};

lcd_context *lcd_get_context() {
    return &ctx;
}

void lcd_init() {
    ctx.lcdc = 0x91;
    ctx.scroll_x = 0;
    ctx.scroll_y = 0;
    ctx.ly = 0;
    ctx.ly_compare = 0;
    ctx.bg_palette = 0xFC;
    ctx.obj_palette[0] = 0xFF;
    ctx.obj_palette[1] = 0xFF;
    ctx.win_x = 0;
    ctx.win_y = 0;
    ctx.lcds = 0x80;

    for(int i = 0; i < 4; i++) {
        ctx.bg_colors[i] = colors_default[i];
        ctx.sp1_colors[i] = colors_default[i];
        ctx.sp2_colors[i] = colors_default[i];
    }
}

u8 lcd_read(u16 address) {
    u8 offset = (address - 0xFF40);
    u8 *p = (u8 *)&ctx;
    return p[offset];
}

void update_palette(u8 palette_data, u8 pal) {
    u32 *p_colors = ctx.bg_colors;

    switch(pal) {
        case 1:
            p_colors = ctx.sp1_colors;
            break;
        case 2:
            p_colors = ctx.sp2_colors;
            break;
    }

    p_colors[0] = colors_default[palette_data & 0b11];
    p_colors[1] = colors_default[(palette_data >> 2) & 0b11];
    p_colors[2] = colors_default[(palette_data >> 4) & 0b11];
    p_colors[3] = colors_default[(palette_data >> 6) & 0b11];
}

void lcd_write(u16 address, u8 value) {
    u8 offset = (address - 0xFF40);
    u8 *p = (u8 *)&ctx;
    p[offset] = value;

    if(offset == 2) {
        //printf("YScroll: %02X\n", value);
    }

    if(offset == 0xA) {
        //printf("WinY: %02X\n", value);
    }

    if(offset == 6) {
        //offset FF64
        dma_start(value);
    }

    if(offset == 7) {
        update_palette(value, 0);
    } else if(offset == 8) {
        update_palette(value & 0b11111100, 1);
    } else if(offset == 9) {
        update_palette(value & 0b11111100, 2);
    }
}

void lcd_save_state(lcd_state* state){
    state->ctx = ctx;
}

void lcd_load_state(const lcd_state* state) {
    ctx = state->ctx;
}