package de.duehl.swing.ui.buttons.painted.state;

/*
 * Copyright 2025 Christian Dühl. All rights reserved.
 *
 * This program is free software. You can redistribute it and/or
 * modify it under the same terms as perl:
 *
 * general:  http://dev.perl.org/licenses/
 * GPL:      http://dev.perl.org/licenses/gpl1.html
 * artistic: http://dev.perl.org/licenses/artistic.html
 */

import java.awt.BasicStroke;
import java.awt.RenderingHints;
import java.awt.geom.Path2D;

import de.duehl.swing.ui.geometry.PixelPoint;

/**
 * Diese Klasse stellt einen kleinen Schalter dar, der ein Herz darstellt.
 *
 * Er kann zwei Zustände darstellen, ausgewählt und nicht ausgewählt. Ist der Zustand aktiviert,
 * wird das Herz ausgefüllt, anderenfalls ist nur dessen Rand zu sehen.
 *
 * @version 1.01     2025-07-24
 * @author Christian Dühl
 */

final public class HeartButton extends PaintedStateButton {

    private static final long serialVersionUID = 1L;

    private static final boolean SHOW_AREA_RECTANGLE = true;

    /** Zeichnet das Symbol in horizontaler und rechteckiger Anordnung. */
    @Override
    protected void paintHorizontalSymbolRectangle() {
        paintSymbol();
    }

    /** Zeichnet das Symbol in vertikaler und rechteckiger Anordnung. */
    @Override
    protected void paintVerticalSymbolRectangle() {
        paintSymbol();
    }

    /** Zeichnet das Symbol in horizontaler und quadratischer Anordnung. */
    @Override
    protected void paintHorizontalSymbolSquare() {
        paintSymbol();
    }

    /** Zeichnet das Symbol in vertikaler und quadratischer Anordnung. */
    @Override
    protected void paintVerticalSymbolSquare() {
        paintSymbol();
    }

    /** Zeichnet das Herz. */
    private void paintSymbol() {
        int width = getWidth();
        int height = getHeight();

        if (width == 35 || height == 35) {
            paint35x35Symbol();
        }
        else {
            paintOtherSymbol();
        }

    }

    private void paint35x35Symbol() {
        int width = getWidth();
        int height = getHeight();

        int correction = 0;
        if (height > width) {
            correction = (height - width) / 2;
        }

        graphics2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        int x = 2;
        int y = correction + 5;
        graphics2.translate(x, y);

        // Herzpfad im kleinen Maßstab
        Path2D path = new Path2D.Double();
        path.moveTo(14.5, 22);
        path.curveTo(4, 14, 2, 5, 9, 5);
        path.curveTo(13, 5, 14.5, 9, 14.5, 9);
        path.curveTo(14.5, 9, 16, 5, 20, 5);
        path.curveTo(27, 5, 25, 14, 14.5, 22);

        if (isElected()) {
            graphics2.fill(path);
        }
        else {
            graphics2.draw(path);
        }

    }

    private void paintOtherSymbol() {
        int width = getWidth();
        int height = getHeight();

        if (isForceSquare()) {
            width = Math.min(width, height);
            height = width;
        }

        int delta = 6;

        int firstLeftPixel = (getWidth() - width)/2;
        int left = firstLeftPixel + delta;

        int lastRightPixel = firstLeftPixel + width - 1;
        int right = lastRightPixel - delta;

        int firstUpperPixel = (getHeight() - height)/2;
        int upper = firstUpperPixel + delta;

        int lastLowerPixel = firstUpperPixel + height - 1;
        int lower = lastLowerPixel - delta;

        if (SHOW_AREA_RECTANGLE) {
            paintLine(new PixelPoint(left, upper), new PixelPoint(right, upper));
            paintLine(new PixelPoint(right, upper), new PixelPoint(right, lower));
            paintLine(new PixelPoint(left, upper), new PixelPoint(left, lower));
            paintLine(new PixelPoint(left, lower), new PixelPoint(right, lower));
        }

        int innerWidth = right - left;
        int innerHeight = lower - upper;
        int centerX = left + innerWidth / 2;
        int centerY = upper + innerHeight / 2;

        int halfSmallerWidthOrHeight = Math.min(width, height) / 2;
        int halfWidthHeight = halfSmallerWidthOrHeight - delta;
        int distance = (int) (halfWidthHeight * 0.43);

        centerY -= halfWidthHeight * 2.18;

        int spitzeX = centerX; int spitzeY = centerY + 100; // untere Spitze

        int anzahlPunkteDelta = 3;
        int [] xDelta = new int[anzahlPunkteDelta];

        xDelta[0] = 3 * distance;
        xDelta[1] = 3 * distance;
        xDelta[2] = 0;

        int [] yDelta = new int[anzahlPunkteDelta];

        yDelta[0] = - distance;
        yDelta[1] = 4 * distance;
        yDelta[2] = 5 * distance;


        int [] leftCurveWerteX = new int[anzahlPunkteDelta];
        int [] leftCurveWerteY = new int[anzahlPunkteDelta];

        int [] rightCurveWerteX = new int[anzahlPunkteDelta];
        int [] rightCurveWerteY = new int[anzahlPunkteDelta];

        for (int index = 0; index < anzahlPunkteDelta; ++index) {
            int deltaX = xDelta[index];
            int deltaY = yDelta[index];

            leftCurveWerteX[index] = centerX - deltaX;
            leftCurveWerteY[index] = centerY + deltaY;

            rightCurveWerteX[index] = centerX + deltaX;
            rightCurveWerteY[index] = centerY + deltaY;
        }

        //graphics2.setStroke(new BasicStroke(2));
        graphics2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        graphics2.setStroke(new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));

        Path2D herz = new Path2D.Double();

        // Linke Hälfte des Herzens
        herz.moveTo(spitzeX, spitzeY); // untere Spitze
        herz.curveTo(
                leftCurveWerteX[0], leftCurveWerteY[0],
                leftCurveWerteX[1], leftCurveWerteY[1],
                leftCurveWerteX[2], leftCurveWerteY[2]);

        // Rechte Hälfte des Herzens
        herz.moveTo(spitzeX, spitzeY); // untere Spitze
        herz.curveTo(
                rightCurveWerteX[0], rightCurveWerteY[0],
                rightCurveWerteX[1], rightCurveWerteY[1],
                rightCurveWerteX[2], rightCurveWerteY[2]);


        if (isElected()) {
            graphics2.fill(herz);
        }
        else {
            graphics2.draw(herz);
        }
    }

}
