package net.ranides.assira.ui.components;

import javax.swing.border.AbstractBorder;
import java.awt.*;

public class CustomBevelBorder extends AbstractBorder {
    public static final int RAISED = 0;
    public static final int LOWERED = 1;

    private final int etchType;
    private final int size;
    private final Color highlight;
    private final Color shadow;

    public CustomBevelBorder(int etchType, int size, Color highlight, Color shadow) {
        this.etchType = etchType;
        this.size = size;
        this.highlight = highlight;
        this.shadow = shadow;
    }

    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
        super.paintBorder(c, g, x, y, width, height);

        int h = height;
        int w = width;

        Graphics2D g2 = (Graphics2D) g.create();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.translate(x, y);

        Polygon topPolygon = createPolygon(pt(0, 0), pt(w, 0), pt(w - size, size), pt(size, size), pt(0, 0));
        g2.setColor(getLTColor(c));
        g2.fill(topPolygon);

        Polygon rightPolygon = createPolygon(pt(w, 0), pt(w, h), pt(w - size, h - size), pt(w - size, size), pt(w, 0));
        g2.setColor(getRBColor(c));
        g2.fill(rightPolygon);

        Polygon bottomPolygon = createPolygon(pt(0, h), pt(w, h), pt(w - size, h - size), pt(size, h - size), pt(0, h));
        g2.setColor(getRBColor(c));
        g2.fill(bottomPolygon);

        Polygon leftPolygon = createPolygon(pt(0, 0), pt(0, h), pt(size, h - size), pt(size, size), pt(0, 0));
        g2.setColor(getLTColor(c));
        g2.fill(leftPolygon);

        g2.dispose();
    }

    private static Point pt(int bw, int h) {
        return new Point(bw, h);
    }

    private static Polygon createPolygon(Point... points) {
        Polygon polygon = new Polygon();
        for (Point point : points) {
            polygon.addPoint(point.x, point.y);
        }
        return polygon;
    }

    @Override
    public Insets getBorderInsets(Component c, Insets insets) {
        insets.set(size, size, size, size);
        return insets;
    }

    @Override
    public boolean isBorderOpaque() {return true;}

    private Color getLTColor(Component c) {
        return etchType == RAISED ? getHighlightColor(c) : getShadowColor(c);
    }

    private Color getRBColor(Component c) {
        return etchType == RAISED ? getShadowColor(c) : getHighlightColor(c);
    }

    private Color getHighlightColor(Component c) {
        return highlight != null ? highlight : c.getBackground().brighter();
    }

    private Color getShadowColor(Component c) {
        return shadow != null ? shadow : c.getBackground().darker();
    }

}
