/src/Palette.js
import Controller from './Controller.js';

const palette_names = [
    "EGA 16-color",
    "Gray/RGB",
    "Red/Blue/Yellow",
    "Purple/Orange/Green",
    "Red/Green",
    "Orange/Blue",
    "Yellow/Purple",
    "Red",
    "Green",
    "Blue",
];
const palettes = [
    [   // Palette 0 - EGA 16-color
        [0x00, 0x00, 0x00], // black
        [0x00, 0x00, 0xAA], // blue
        [0x00, 0xAA, 0x00], // green
        [0x00, 0xAA, 0xAA], // cyan
        [0xAA, 0x00, 0x00], // red
        [0xAA, 0x00, 0xAA], // magenta
        [0xAA, 0x55, 0x00], // brown
        [0xAA, 0xAA, 0xAA], // light gray
        [0x55, 0x55, 0x55], // dark gray
        [0x55, 0x55, 0xFF], // bright blue
        [0x55, 0xFF, 0x55], // bright green
        [0x55, 0xFF, 0xFF], // bright cyan
        [0xFF, 0x55, 0x55], // bright red
        [0xFF, 0x55, 0xFF], // bright magenta
        [0xFF, 0xFF, 0x55], // bright yellow
        [0xFF, 0xFF, 0xFF], // white
    ],
    [   // Palette 1 - Gray4/R4/G4/B4
        [0x00, 0x00, 0x00],
        [0x3B, 0x3B, 0x3B],
        [0x76, 0x76, 0x76],
        [0xB8, 0xB8, 0xB8],
        [0x68, 0x00, 0x00],
        [0x9E, 0x00, 0x00],
        [0xD7, 0x00, 0x00],
        [0xFE, 0x41, 0x41],
        [0x00, 0x39, 0x00],
        [0x00, 0x59, 0x00],
        [0x00, 0x7C, 0x00],
        [0x00, 0xA0, 0x00],
        [0x00, 0x2B, 0x71],
        [0x00, 0x46, 0xAA],
        [0x00, 0x61, 0xE7],
        [0x54, 0x83, 0xFE],
    ],
    [   // Palette 2 - Black/R5/B5/Yellow5
        [0x00, 0x00, 0x00],
        [0x54, 0x00, 0x00],
        [0x7D, 0x00, 0x00],
        [0xA9, 0x00, 0x00],
        [0xD7, 0x00, 0x00],
        [0xFE, 0x27, 0x28],
        [0x00, 0x22, 0x5B],
        [0x00, 0x36, 0x87],
        [0x00, 0x4B, 0xB6],
        [0x00, 0x61, 0xE7],
        [0x44, 0x7C, 0xFE],
        [0x43, 0x43, 0x00],
        [0x70, 0x70, 0x00],
        [0xA1, 0xA1, 0x00],
        [0xD4, 0xD5, 0x00],
        [0xFF, 0xFE, 0xFE],
    ],
    [   // Palette 3 - Black/Purple5/Orange5/Green5
        [0x00, 0x00, 0x00],
        [0x4B, 0x00, 0x43],
        [0x70, 0x00, 0x65],
        [0x98, 0x00, 0x89],
        [0xC1, 0x00, 0xAF],
        [0xED, 0x00, 0xD6],
        [0x48, 0x2D, 0x00],
        [0x73, 0x4B, 0x00],
        [0xA2, 0x6B, 0x00],
        [0xD2, 0x8D, 0x00],
        [0xFF, 0xB2, 0x48],
        [0x00, 0x2D, 0x00],
        [0x00, 0x46, 0x00],
        [0x00, 0x60, 0x00],
        [0x00, 0x7C, 0x00],
        [0x00, 0x99, 0x00],
    ],
    [   // Palette 4 - Red/Green
        [0x41, 0x00, 0x00],
        [0x68, 0x00, 0x00],
        [0x7D, 0x00, 0x00],
        [0x93, 0x00, 0x00],
        [0xA9, 0x00, 0x00],
        [0xC0, 0x00, 0x00],
        [0xD7, 0x00, 0x00],
        [0xEF, 0x00, 0x00],
        [0x00, 0x21, 0x00],
        [0x00, 0x39, 0x00],
        [0x00, 0x46, 0x00],
        [0x00, 0x53, 0x00],
        [0x00, 0x60, 0x00],
        [0x00, 0x6E, 0x00],
        [0x00, 0x7C, 0x00],
        [0x00, 0x8A, 0x00],
    ],
    [   // Palette 5 - Orange/Blue
        [0x48, 0x2D, 0x00],
        [0x5D, 0x3C, 0x00],
        [0x73, 0x4B, 0x00],
        [0x8A, 0x5B, 0x00],
        [0xA2, 0x6B, 0x00],
        [0xBA, 0x7B, 0x00],
        [0xD2, 0x8D, 0x00],
        [0xEC, 0x9E, 0x00],
        [0x00, 0x22, 0x5B],
        [0x00, 0x2B, 0x71],
        [0x00, 0x36, 0x87],
        [0x00, 0x40, 0x9E],
        [0x00, 0x4B, 0xB6],
        [0x00, 0x56, 0xCE],
        [0x00, 0x61, 0xE7],
        [0x0D, 0x6D, 0xFE],
    ],
    [   // Palette 6 - Yellow/Purple
        [0x2E, 0x2E, 0x00],
        [0x59, 0x59, 0x00],
        [0x70, 0x70, 0x00],
        [0x88, 0x88, 0x00],
        [0xA1, 0xA1, 0x00],
        [0xBA, 0xBB, 0x00],
        [0xD4, 0xD5, 0x00],
        [0xEF, 0xEF, 0x00],
        [0x39, 0x00, 0x33],
        [0x5D, 0x00, 0x53],
        [0x70, 0x00, 0x65],
        [0x83, 0x00, 0x77],
        [0x98, 0x00, 0x89],
        [0xAC, 0x00, 0x9C],
        [0xC1, 0x00, 0xAF],
        [0xD7, 0x00, 0xC2],
    ],
    [   // Palette 7 - Red
        [0x22, 0x00, 0x00],
        [0x32, 0x00, 0x00],
        [0x3E, 0x00, 0x00],
        [0x4A, 0x00, 0x00],
        [0x56, 0x00, 0x00],
        [0x63, 0x00, 0x00],
        [0x70, 0x00, 0x00],
        [0x7D, 0x00, 0x00],
        [0x8B, 0x00, 0x00],
        [0x98, 0x00, 0x00],
        [0xA6, 0x00, 0x00],
        [0xB4, 0x00, 0x00],
        [0xC3, 0x00, 0x00],
        [0xD1, 0x00, 0x00],
        [0xE0, 0x00, 0x00],
        [0xEF, 0x00, 0x00],
    ],
    [   // Palette 8 - Green
        [0x00, 0x0F, 0x00],
        [0x00, 0x18, 0x00],
        [0x00, 0x20, 0x00],
        [0x00, 0x27, 0x00],
        [0x00, 0x2E, 0x00],
        [0x00, 0x36, 0x00],
        [0x00, 0x3E, 0x00],
        [0x00, 0x46, 0x00],
        [0x00, 0x4E, 0x00],
        [0x00, 0x56, 0x00],
        [0x00, 0x5F, 0x00],
        [0x00, 0x67, 0x00],
        [0x00, 0x70, 0x00],
        [0x00, 0x78, 0x00],
        [0x00, 0x81, 0x00],
        [0x00, 0x8A, 0x00],
    ],
    [   // Palette 9 - Blue
        [0x00, 0x09, 0x25],
        [0x00, 0x11, 0x37],
        [0x00, 0x17, 0x44],
        [0x00, 0x1D, 0x50],
        [0x00, 0x23, 0x5E],
        [0x00, 0x29, 0x6B],
        [0x00, 0x2F, 0x79],
        [0x00, 0x36, 0x87],
        [0x00, 0x3C, 0x95],
        [0x00, 0x43, 0xA4],
        [0x00, 0x4A, 0xB3],
        [0x00, 0x51, 0xC2],
        [0x00, 0x58, 0xD1],
        [0x00, 0x5F, 0xE1],
        [0x00, 0x66, 0xF1],
        [0x0D, 0x6D, 0xFE],
    ],
]

export default class Palette extends Controller {
    constructor(appState) {
        super(appState);
        this.node = document.getElementById('palette');
        this.swatches = [];
        for (let i = 0; i < this.node.children.length; i++) {
            let c = this.node.children[i];
            if (c.className == 'swatch') {
                let n = this.swatches.length;
                c.addEventListener('mousedown', event => this.selectColor(n))
                c.addEventListener('dblclick', event => this.editColor(n));
                this.swatches.push(c);
            }
        }

        this.selectPalette(0);
        this.selectColor(0);
    }

    selectPalette(n) {
        this.palette = n;
        let p = palettes[n];
        for (i = 0; i < 16; i++) {
            this.swatches[i].style.backgroundColor = 'rgb(' + p[i][0] + ',' + p[i][1] + ',' + p[i][2] + ')';
        }
        document.getElementById('palette-id').textContent = palette_names[n];
    }
    nextPalette() {
        this.selectPalette((this.palette + 1) % palettes.length);
    }
    prevPalette() {
        let newPalette = this.palette - 1;
        if (newPalette < 0)
            newPalette = palettes.length - 1;
        this.selectPalette(newPalette);
    }
    selectColor(n) {
        if (this.color != undefined)
            this.swatches[this.color].className = 'swatch';
        this.color = n;
        this.swatches[this.color].className = 'swatch selected';
    }
    getCSSColor(i = this.color) {
        let c = palettes[this.palette][i];
        return 'rgb(' + c[0] + ',' + c[1] + ',' + c[2] + ')';
    }
    findClosestColor(rgbdata) {
        let closest = 0;
        let distance = 1e9;
        for (let i = 0; i < 16; i++) {
            let tc = palettes[this.palette][i];
            let d = Math.pow(
                Math.abs(tc[0] - rgbdata[0]) + Math.abs(tc[1] - rgbdata[1]) + Math.abs(tc[2] - rgbdata[2]),
                1/3
            );
            if (d < distance) {
                closest = i;
                distance = d;
            }
        }

        return closest;
    }
    editColor(n) {
        let colorpicker = document.getElementById('dialog-colorpicker');
        colorpicker.style.display = null;
        let colorpicker_color = document.getElementById('colorpicker-color');
        let colorpicker_red = document.getElementById('colorpicker-red');
        let colorpicker_green = document.getElementById('colorpicker-green');
        let colorpicker_blue = document.getElementById('colorpicker-blue');
        let colorpicker_ok = document.getElementById('colorpicker-ok');
        let colorpicker_cancel = document.getElementById('colorpicker-cancel');

        let currentPalette = this.palette;
        colorpicker_red.value = palettes[currentPalette][n][0];
        colorpicker_green.value = palettes[currentPalette][n][1];
        colorpicker_blue.value = palettes[currentPalette][n][2];

        let changefunc = () => {
            let r = colorpicker_red.value;
            let g = colorpicker_green.value;
            let b = colorpicker_blue.value;
            colorpicker_color.style.backgroundColor = 'rgb(' + r + ',' + g + ',' + b + ')';
        };
        colorpicker_red.onkeyup = changefunc;
        colorpicker_green.onkeyup = changefunc;
        colorpicker_blue.onkeyup = changefunc;
        changefunc();

        colorpicker_cancel.onclick = () => {
            colorpicker.style.display = 'none';
        }

        colorpicker_ok.onclick = () => {
            palette_names[currentPalette] = "Custom " + n;
            let r = colorpicker_red.value;
            let g = colorpicker_green.value;
            let b = colorpicker_blue.value;
            palettes[currentPalette][n] = [r, g, b];
            this.selectPalette(currentPalette);
            this.state.pixelEditor.redraw();
            this.state.pixelEditor.refresh();
            colorpicker.style.display = 'none';
        }
    }
}