package de.duehl.swing.ui.tables;

/*
 * Copyright 2024 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.Color;
import java.awt.Component;
import java.awt.Font;

import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;

import de.duehl.swing.ui.colors.ColorTool;

/**
 * Diese Klasse ist für das Rendern (die optische Darstellung) der Tabellenzellen zuständig. Sie
 * wurde von DefaultTableCellRenderer abgeleitet, um nicht für jede Zelle eine neue Klasse zu
 * erzeugen.
 *
 * TODO Vielleicht kann man später diese Klasse zu DifferentBackgroundsTableRenderer machen.
 *      Das muss man dann aber testen.
 *
 * @version 1.01     2024-07-25
 * @author Christian Dühl
 */

public class DifferentBackgroundsTableRendererWithChangingSize extends DefaultTableCellRenderer {

    private static final long serialVersionUID = 1L;

    private static final float DEFAULT_FONT_SIZE = 15f;

    /** Die hellere Vordergrundfarbe. */
    private final Color lighterForeground;

    /** Die hellere Hintergrundfarbe. */
    private final Color lighterBackground;

    /** Die dunklere Vordergrundfarbe. */
    private final Color darkerForeground;

    /** Die dunklere Hintergrundfarbe. */
    private final Color darkerBackground;

    /** Die Schriftgröße der in der Tabelle angezeigten Texte. */
    private float fontSize;

    /**
     * Gibt an, ob bei selektierten Zeilen die Farben von Vorder- und Hintergrund vertauscht werden
     * sollen.
     */
    private boolean useSwitchedColorsForSelection;

    /** Gibt an, ob wirklich unterschiedliche Hintergründe benutzt werden sollen. */
    private boolean useDifferentBackgrounds;

    /** Die normale Vordergrundfarbe. */
    private Color normalForground;

    /** Die normale Hintergrundfarbe. */
    private Color normalBackground;

    /**
     * Der Konstruktor, hier werden unsere Maps erzeugt.
     *
     * @param foregroundColor
     *            Vordergrundfarbe
     * @param backgroundColor
     *            Hintergrundfarbe
     */
    public DifferentBackgroundsTableRendererWithChangingSize(Color foregroundColor,
            Color backgroundColor) {
        super();

        lighterForeground = ColorTool.calculateLighterColor(foregroundColor);
        lighterBackground = ColorTool.calculateLighterColor(backgroundColor);

        darkerForeground = ColorTool.calculateDarkerColor(foregroundColor);
        darkerBackground = ColorTool.calculateDarkerColor(backgroundColor);

        normalForground = foregroundColor;
        normalBackground = backgroundColor;

        useSwitchedColorsForSelection = true;
        fontSize = DEFAULT_FONT_SIZE;
        useDifferentBackgrounds = true;
    }

    /**
     * Legt fest, dass für die Selection die gleichen Farben genutzt werden wir für die normale
     * Darstellung.
     */
    public void doNotUseSwitchedColorsForSelection() {
        useSwitchedColorsForSelection = false;
    }

    /**
     * Gibt an, ob bei selektierten Zeilen die Farben von Vorder- und Hintergrund vertauscht werden
     * sollen.
     */
    public boolean isUseSwitchedColorsForSelection() {
        return useSwitchedColorsForSelection;
    }

    /** Legt fest, ob wirklich unterschiedliche Hintergründe benutzt werden sollen. */
    public void setUseDifferentBackgrounds(boolean useDifferentBackgrounds) {
        this.useDifferentBackgrounds = useDifferentBackgrounds;
    }

    /**
     * Liefert eine Komponente für die anzuzeigende Zelle zurück. Die Hauptarbeit lassen wir
     * super.getTableCellRendererComponent(...) machen und hängen nur ein wenig Code dahinter.
     *
     * @param table
     *            Die Tabelle
     * @param value
     *            Das anzuzeigende Objekt (im Normalfall ein String)
     * @param isSelected
     *            Zeigt an, ob das Objekt selektiert wurde.
     * @param hasFocus
     *            Zeigt an, ob der Focus auf dieser Zelle liegt.
     * @param row
     *            Zeile in der die Zelle liegt.
     * @param column
     *            Spalte in der die Zelle liegt.
     */
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
            boolean hasFocus, int row, int column) {
        JLabel createdLabel = (JLabel) super.getTableCellRendererComponent(table, value, isSelected,
                hasFocus, row, column);
        //createdLabel.setFont(new Font("Arial", Font.BOLD, 30));
        //setVerticalAlignment(JLabel.CENTER);
        //setHorizontalAlignment(JLabel.LEFT);


        Font oldFont = createdLabel.getFont();
        createdLabel.setFont(oldFont.deriveFont(fontSize));
        //c.setFont(new Font("Arial", Font.BOLD, 30));
        setVerticalAlignment(JLabel.CENTER);
        setHorizontalAlignment(JLabel.LEFT);

        //table.setRowHeight((int) (tableFontSize * 1.6));
        //table.setRowHeight(20);
        // Das geht nicht, das führt zu rekursiven Aufrufen dieser Methode,
        // wodurch die CPU-Last auf 100% geht.
        // Besser beim erstellen der Tabelle die Zeilenhöhe ändern:
        //     table.setRowHeight((int) (1.6 * tableFontSize));

        Color foreground;
        Color background;
        if (useDifferentBackgrounds) {
            boolean odd = row % 2 == 0;
            foreground = odd ? lighterForeground : darkerForeground;
            background = odd ? lighterBackground : darkerBackground;
        }
        else {
            foreground = normalForground;
            background = normalBackground;
        }

        if (isSelected && useSwitchedColorsForSelection) {
            setForeground(background);
            setBackground(foreground);
        }
        else {
            setForeground(foreground);
            setBackground(background);
        }

        return createdLabel;
    }

    /** Initialisiert die Zeilenhöhe der Tabelle. */
    public void initRowHeightOfTable(JTable table) {
        int tableRowHeight = (int) (1.6 * fontSize);
        table.setRowHeight(tableRowHeight);
    }

    /**
     * Verringert die Schriftgröße.
     *
     * Will man auch die Zeilenhöhe anpassen, so sollte man im Anschluss
     * initRowHeightOfTable(table) aufrufen.
     *
     * Die Tabelle muss danach neu gezeichnet werden, damit die neue Schriftgröße zu sehen ist.
     */
    public void increaseFontSize() {
        fontSize += 1f;
    }

    /**
     * Erhöht die Schriftgröße.
     *
     * Will man auch die Zeilenhöhe anpassen, so sollte man im Anschluss
     * initRowHeightOfTable(table) aufrufen.
     *
     * Die Tabelle muss danach neu gezeichnet werden, damit die neue Schriftgröße zu sehen ist.
     */
    public void decreaseFontSize() {
        fontSize -= 1f;
    }

    /**
     * Setzt die Schriftgröße.
     *
     * Will man auch die Zeilenhöhe anpassen, so sollte man im Anschluss
     * initRowHeightOfTable(table) aufrufen.
     *
     * Die Tabelle muss danach neu gezeichnet werden, damit die neue Schriftgröße zu sehen ist.
     *
     * @param fontSize
     *            Die neue Schriftgröße.
     */
    public void setFontSize(float fontSize) {
        this.fontSize = fontSize;
    }

    /** Getter für die aktuelle Schriftgröße. */
    public float getFontSize() {
        return fontSize;
    }

}
