package a.test2;

import ca.tecreations.Color;
import ca.tecreations.ImageTool;
import ca.tecreations.Pixel;
import ca.tecreations.Point;
import ca.tecreations.components.Magnifier;

import com.sun.jna.Pointer;

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;

   
public class LoadCursor {
    public static final String APP_STARTING = "app_starting";
    public static final String DEFAULT = "default";
    public static final String DONUT = "donut";
    public static final String EW = "ew";
    public static final String HAND = "hand";
    public static final String HELP = "help";
    public static final String IBEAM = "ibeam";
    public static final String MOVE = "move";
    public static final String N_ARROW = "n_arrow";
    public static final String NESW = "nesw";
    public static final String NO = "no";
    public static final String NS = "ns";
    public static final String NWSE = "nwse";
    public static final String SIZE_ALL = "size_all";
    public static final String SIZE_NESW = "size_nesw";
    public static final String SIZE_NS = "size_ns";
    public static final String SIZE_NWSE = "size_nwse";
    public static final String SIZE_WE = "size_we";
    public static final String UP_ARROW = "up_arrow";
    public static final String WAIT = "wait";
    
    public static List<String> names = new ArrayList<>();
    static {
        names.add(APP_STARTING);
        names.add(DEFAULT);
        names.add(DONUT);
        names.add(EW);
        names.add(HAND);
        names.add(HELP);
        //names.add(IBEAM);
        names.add(MOVE);
        names.add(N_ARROW);
        names.add(NESW);
        names.add(NO);
        names.add(NS);
        names.add(NWSE);
        names.add(SIZE_ALL);
        names.add(SIZE_NESW);
        names.add(SIZE_NS);
        names.add(SIZE_NWSE);
        names.add(SIZE_WE);
        names.add(UP_ARROW);
        names.add(WAIT);
    }
    // makeFinal("~'a.test2.LoadCursor.names[{(List<String>)}]'~");

    public static final LoadCursor instance = new LoadCursor();
    public static Magnifier magnifier;
    
    public static final int TEC_MASK_RGB = Color.TEC_PURPLE.getRGB();
    int width;
    int height;
    public static List<Pixel> pixels;
    public static List<Point> maskPoints;
    
    private List<Pixel> squashed;
    
    public LoadCursor() {
    }
    
    // ok, addName(String name), where's the data?
    
    private void applyMask(BufferedImage image, BufferedImage mask) {
        pixels = new ArrayList<>();
        maskPoints = new ArrayList<>();
        int width = image.getWidth();
        int height = image.getHeight();
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                int masked = mask.getRGB(x, y);
                if ((masked & 0x00FFFFFF) == 0) {
                    int rgb = image.getRGB(x, y);
                    rgb = 0xFF000000 | rgb;
                    image.setRGB(x, y, rgb);
                    pixels.add(new Pixel(new Color(rgb),x,y));
                } else {
                    image.setRGB(x,y,TEC_MASK_RGB);
                    maskPoints.add(new Point(x,y));
                }
            }
        }
    }

    public BufferedImage draw(BufferedImage image, int cursor, int diFlags) {
        a.test2.User32 user32 = a.test2.User32.INSTANCE;
        Gdi32 gdi32 = Gdi32.INSTANCE;
        Pointer hIcon = user32.LoadCursorW(Pointer.NULL, cursor);
        Pointer hdc = gdi32.CreateCompatibleDC(Pointer.NULL);
        int width = image.getWidth();
        int height = image.getHeight();
        Pointer bitmap = gdi32.CreateCompatibleBitmap(hdc,width, height);

        
        gdi32.SelectObject(hdc, bitmap);
        user32.DrawIconEx(hdc, 0, 0, hIcon, width, height, 0,
        Pointer.NULL, diFlags);

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                int rgb = gdi32.GetPixel(hdc, x, y);
                image.setRGB(x, y, rgb);
            }
        }
        gdi32.DeleteObject(bitmap);
        gdi32.DeleteDC(hdc);
        return image;
    }

    public BufferedImage getCursorByIndex(int id) {
        final int width = 32;
        final int height = 32;
    
        BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_ARGB);
        draw(image, id, User32.DI_NORMAL);
        BufferedImage mask = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        draw(mask, id, User32.DI_MASK);
        applyMask(image, mask);
        return image;
    }

    public BufferedImage getForTec(String name) {
        BufferedImage image = getWinCursor(name);
        return getSquashedFor(image,Color.TEC_PURPLE.getRGB());
    }
    
    public int getID(String name) {
        name = name.toLowerCase();
        if (name.equals("app_starting")) return User32.IDC_APPSTARTING;
        if (name.equals("default")) return 32512;
        if (name.equals("donut")) return 32514;
        if (name.equals("ew")) return 36444;
        if (name.equals("hand")) return User32.IDC_HAND;
        if (name.equals("help")) return User32.IDC_HELP;
        if (name.equals("move")) return 32646;
        if (name.equals("n_arrow")) return 32516;
        if (name.equals("nesw")) return 32643;
        if (name.equals("no")) return User32.IDC_NO;
        if (name.equals("ns")) return 32645;
        if (name.equals("nwse")) return 32642;
        if (name.equals("size_all")) return User32.IDC_SIZEALL;
        if (name.equals("size_nesw")) return User32.IDC_SIZENESW;
        if (name.equals("size_ns")) return User32.IDC_SIZENS;
        if (name.equals("size_nwse")) return User32.IDC_SIZENWSE;
        if (name.equals("size_we")) return User32.IDC_SIZEWE;
        if (name.equals("up_arrow")) return User32.IDC_UPARROW;
        if (name.equals("wait")) return User32.IDC_WAIT;
        return -1; // not found
    }
    
    public List<Point> getMaskPoints() {
        return maskPoints;
    }

    public static String getName(int id) {
        String idString = "app_starting";
        if (id == 32512) idString = "default";
        else if (id == 32514) idString = "donut";
        else if (id == 32644) idString = "ew";
        else if (id == User32.IDC_HAND) idString = "hand";
        else if (id == User32.IDC_HELP) idString = "help";
        else if (id == 32646) idString = "move";
        else if (id == 32516) idString = "n_arrow";
        else if (id == 32643) idString = "nesw";
        else if (id == User32.IDC_NO) idString = "no";
        else if (id == 32645) idString = "ns";
        else if (id == 32642) idString = "nwse";
        else if (id == User32.IDC_SIZEALL) idString = "size_all";
        else if (id == User32.IDC_SIZENESW) idString = "size_nesw";
        else if (id == User32.IDC_SIZENS) idString = "size_ns";
        else if (id == User32.IDC_SIZENWSE) idString = "size_nwse";
        else if (id == User32.IDC_SIZEWE) idString = "size_we";
        else if (id == User32.IDC_UPARROW) idString = "up_arrow";
        else if (id == User32.IDC_WAIT)  idString = "wait";
        return idString;
    }
    
    public List<Pixel> getPixels() { return pixels; }
    
    public void getRandom() {
        
    }
    public List<Pixel> getSquashedPixels() {
        return squashed;
    }
    
    protected/*AgainstTheft*/ BufferedImage getSquashedFor(BufferedImage image, int maskRGB) {
        pixels = ImageTool.getPixels(image);
        squashed = new ArrayList<>();
        maskPoints = new ArrayList<>();
        BufferedImage test = ImageTool.getNewBufferedImage(pixels);
        Pixel p;
        int w = image.getWidth();
        
        for(int y = 0; y < image.getHeight();y++) {
            for(int x = 0; x < w;x++) {
                p = pixels.get(y * w + x);
                if (p.getColor().getRGB() != maskRGB) {
                    squashed.add(p);
                } else {
                    maskPoints.add(new Point(x,y));
                }
            }
        }
        
        //System.err.println("Image cells: "  + (image.getWidth() * image.getHeight()) + " Squashed.size: " + squashed.size());
        
        if (squashed.size() == 0) {
            return image;
        } else {
            int maxX = 0;
            int maxY = 0;
            for(int i = 0; i < squashed.size();i++) {
                maxX = Math.max(maxX,squashed.get(i).getX());
                maxY = Math.max(maxY,squashed.get(i).getY());
            }
            maxX++;
            maxY++;
            int minX = maxX;
            int minY = maxY;
            for(int i = 0; i < squashed.size();i++) {
                minX = Math.min(minX,squashed.get(i).getX());
                minY = Math.min(minY,squashed.get(i).getY());
            }
            int newWidth = maxX - minX;
            int newHeight = maxY - minY;
            BufferedImage img = ImageTool.getNewBufferedImage(newWidth,newHeight);
            Graphics g = img.getGraphics();
            g.setColor(new Color(maskRGB)); // decide on a constant to use
            g.fillRect(0,0,newWidth,newHeight);
            for(int i = 0;i < squashed.size();i++) {
                p = squashed.get(i);
                g.setColor(p.getColor());
                int newX = p.getX() - minX;
                int newY = p.getY() - minY;
                p.setPXY(newX,newY);
                g.drawLine(newX,newY,newX,newY);
            }
            width = newWidth;
            height = newHeight;
            return img;
        }
    }
    
    public BufferedImage getWinCursor(String name) {
        int id = LoadCursor.instance.getID(name);
        return getCursorByIndex(id);
    }
    
    public BufferedImage getWinCursor(int id) {
        return getCursorByIndex(id);
    }
    
    public static void main(String[] args) {
        LoadCursor lc = new LoadCursor();
        for(int i = 0; i < names.size();i++) {
            BufferedImage squashed = lc.getForTec(names.get(i));
            Magnifier magnifier = new Magnifier(squashed);
            magnifier.waitForClose();
        }
        
    }
    
}