package me.hammerle.supersnuvi.javafx;

import javafx.scene.image.PixelReader;
import javafx.scene.image.PixelWriter;

public abstract class Image 
{
    private javafx.scene.image.Image[] colored;
    private int slot = -1;
    
    public Image()
    {
        colored = new javafx.scene.image.Image[0];
    }
    
    public void bindSlot(int slot)
    {
        this.slot = slot;
    }
    
    public void createSlot(int r, int g, int b, int alpha)
    {
        if(getImage() == null)
        {
            return;
        }
        javafx.scene.image.Image[] newColored = new javafx.scene.image.Image[colored.length + 1];
        System.arraycopy(colored, 0, newColored, 0, colored.length);
        javafx.scene.image.Image image = getImage();
        PixelReader reader = image.getPixelReader();
        int w = (int) image.getWidth();
        int h = (int) image.getHeight();
        javafx.scene.image.WritableImage wi = new javafx.scene.image.WritableImage(w, h);
        PixelWriter writer = wi.getPixelWriter();
        newColored[colored.length] = wi;
        colored = newColored;
        
        int argb = (alpha << 24) | (r << 16) | (g << 8) | b;
        for(int x = 0; x < w; x++)
        {
            for(int y = 0; y < h; y++)
            {
                writer.setArgb(x, y, mixColor(reader.getArgb(x, y), r, g, b, alpha));
            }
        }
    }
    
    private int mixColor(int argb, int r, int g, int b, int alpha)
    {
        if(argb == 0)
        {
            return 0;
        }
        int br = (((argb >> 16) & 0xFF) + r) >> 1;
        int bg = (((argb >> 8) & 0xFF) + g) >> 1;
        int bb = ((argb & 0xFF) + b) >> 1;
        int ba = (((argb >> 24) & 0xFF) + alpha) >> 1;
        return (ba << 24) | (br << 16) | (bg << 8) | bb;
    }
    
    protected final javafx.scene.image.Image getImageSlot()
    {
        if(slot < 0 || slot >= colored.length)
        {
            return getImage();
        }
        return colored[slot];
    }
    
    protected abstract javafx.scene.image.Image getImage();
    
    public abstract double getWidth();
    public abstract double getHeight();
}
