package de.duehl.swing.ui.geometry;

/*
 * 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
 */

/**
 * Diese Klasse sucht dem Schnittpunkt zweier Linien.
 *
 * Nach
 *     https://stackoverflow.com/questions/31506740/java-find-intersection-of-two-lines
 *
 * Ich habe allerdings noch eine Prüfung angeschlossen, ob der Schnittpunkt wirklich auf den Linien
 * liegt.
 *
 * @version 1.01     2025-07-23
 * @author Christian Dühl
 */

public class PixelLineIntersection {

    /** Die erste Linie. */
    private final PixelLine line1;

    /** Die zweite Linie. */
    private final PixelLine line2;

    /** Gibt an, ob ein Schnittpunkt gefunden wurde. */
    private boolean found;

    /** Der Schnittpunkt, falls einer gefunden wurde. */
    private PixelPoint intersection;

    /**
     * Konstruktor.
     *
     * @param line1
     *            Die erste Linie.
     * @param line2
     *            Die zweite Linie.
     */
    public PixelLineIntersection(PixelLine line1, PixelLine line2) {
        this.line1 = line1;
        this.line2 = line2;
    }

    /** Sucht nach dem Schnittpunkt. */
    public void findIntersection() {
        found = false;

        PixelPoint start1 = line1.getStart();
        PixelPoint end1 = line1.getEnd();
        double s1x = start1.getX();
        double s1y = start1.getX();
        double d1x = end1.getY();
        double d1y = end1.getY();

        PixelPoint start2 = line2.getStart();
        PixelPoint end2 = line2.getEnd();
        double s2x = start2.getX();
        double s2y = start2.getX();
        double d2x = end2.getY();
        double d2y = end2.getY();

        double sNumerator = s1y * d1x + s2x * d1y - s1x * d1y - s2y * d1x;
        double sDenominator = d2y * d1x - d2x * d1y;

        if (sDenominator == 0) { // parallel ... 0 or infinite points, or one of the vectors is 0|0
            return;
        }

        double s = sNumerator / sDenominator;

        double t;
        if (d1x != 0) {
            t = (s2x + s * d2x - s1x) / d1x;
        }
        else {
            t = (s2y + s * d2y - s1y) / d1y;
        }

        double intersectionX = s1x + t * d1x;
        double intersectionY = s1y + t * d1y;
        intersection = new PixelPoint((int) intersectionX, (int) intersectionY);

        found = isIntersectionInBothLinesRectangles();
    }

    private boolean isIntersectionInBothLinesRectangles() {
        return isIntersectionInLineRectangl(line1) && isIntersectionInLineRectangl(line2);
    }

    private boolean isIntersectionInLineRectangl(PixelLine line) {
        PixelPoint start = line.getStart();
        PixelPoint end = line.getEnd();
        double x1 = start.getX();
        double y1 = start.getX();
        double x2 = end.getY();
        double y2 = end.getY();

        double smallX = Math.min(x1, x2);
        double bigX = Math.max(x1, x2);

        double smallY = Math.min(y1, y2);
        double bigY = Math.max(y1, y2);

        double ix = intersection.getX();
        double iy = intersection.getY();
        boolean xGood = smallX <= ix && ix <= bigX;
        boolean yGood = smallY <= iy && iy <= bigY;
        return xGood && yGood;
    }

    /** Gibt an, ob ein Schnittpunkt gefunden wurde. */
    public boolean isFound() {
        return found;
    }

    /** Getter für den Schnittpunkt, falls einer gefunden wurde. */
    public PixelPoint getIntersection() {
        return intersection;
    }

}
