package de.duehl.swing.ui.tabs;

/*
 * Copyright 2017 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.FlowLayout;

import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;

import de.duehl.swing.ui.colors.Colorizer;
import de.duehl.swing.ui.tabs.close.CloseButtonReaktor;
import de.duehl.swing.ui.tabs.close.CloseTabButton;

/**
 * Diese Klasse stellt die Komponente, die oben in der Fahne der Reiter dargestellt wird und den
 * Titel des Reiters sowie einen Knopf zum Schließen beinhaltet.
 *
 * @version 1.01     2017-11-27
 * @author Christian Dühl
 */

public class Tabulator extends JPanel implements ChangeStateDisplayer {

    private static final long serialVersionUID = 1L;

    /**
     * Eindeutige Bezeichnung des Tabulators, wie etwa der Name einer Datei, das Login eines
     * Benutzers oder die ID der Gruppe, zu dem bzw. der der Reiter gehört.
     */
    private final String tabIdentifier;

    /** Anzuzeigender Name des Reiters. */
    private String name;

    /** Label, das den Namen des Reiters anzeigt. */
    private JLabel nameLabel;

    /** Gibt an, ob der Button zum Löschen angezeigt werden soll. */
    private final boolean showCloseButton;

    /** Der kleine Schalter zum Schließen. */
    private CloseTabButton closeButton;

    /** Farbverwaltung für die Gui. */
    private Colorizer colorizer;

    /** Vordergrundfarbe des Namenfeldes. */
    private Color originalForeground;

    /** Gibt an, ob der Name des Tabulators nicht geändert werden soll. */
    private boolean changeName;

    /**
     * Konstruktor mit Schalter zum Schließen.
     *
     * @param tabIdentifier
     *            Login des Benutzers oder ID der Gruppe, zu dem bzw. der der
     *            Reiter gehört.
     * @param name
     *            Anzuzeigender Name des Reiters.
     */
    public Tabulator(String tabIdentifier, String name) {
        this(tabIdentifier, name, createDoNothingCloseReaktor(), true);
    }

    /**
     * Konstruktor.
     *
     * @param tabIdentifier
     *            Login des Benutzers oder ID der Gruppe, zu dem bzw. der der Reiter gehört.
     * @param name
     *            Anzuzeigender Name des Reiters.
     * @param showCloseButton
     *            Gibt an, ob der Button zum Löschen angezeigt werden soll.
     */
    public Tabulator(String tabIdentifier, String name, boolean showCloseButton) {
        this(tabIdentifier, name, createDoNothingCloseReaktor(), showCloseButton);
    }

    /**
     * Konstruktor mit Schalter zum Schließen.
     *
     * @param tabIdentifier
     *            Login des Benutzers oder ID der Gruppe, zu dem bzw. der der
     *            Reiter gehört.
     * @param name
     *            Anzuzeigender Name des Reiters.
     * @param reaktor
     *            Objekt, das über das Schließen des Reiters informiert wird.
     */
    public Tabulator(String tabIdentifier, String name, CloseButtonReaktor reaktor) {
        this(tabIdentifier, name, reaktor, null, true);
    }

    /**
     * Konstruktor
     *
     * @param tabIdentifier
     *            Login des Benutzers oder ID der Gruppe, zu dem bzw. der der
     *            Reiter gehört.
     * @param name
     *            Anzuzeigender Name des Reiters.
     * @param reaktor
     *            Objekt, das über das Schließen des Reiters informiert wird.
     * @param showCloseButton
     *            Gibt an, ob der Button zum Löschen angezeigt werden soll.
     */
    public Tabulator(String tabIdentifier, String name, CloseButtonReaktor reaktor,
            boolean showCloseButton) {
        this(tabIdentifier, name, reaktor, null, showCloseButton);
    }

    /**
     * Konstruktor
     *
     * @param tabIdentifier
     *            Login des Benutzers oder ID der Gruppe, zu dem bzw. der der Reiter gehört.
     * @param name
     *            Anzuzeigender Name des Reiters.
     * @param reaktor
     *            Objekt, das über das Schließen des Reiters informiert wird.
     * @param colorizer
     *            Objekt zum Einfärben der Komponente.
     */
    public Tabulator(String tabIdentifier, String name, CloseButtonReaktor reaktor,
            Colorizer colorizer) {
        this(tabIdentifier, name, reaktor, colorizer, true);
    }

    /**
     * Konstruktor
     *
     * @param tabIdentifier
     *            Login des Benutzers oder ID der Gruppe, zu dem bzw. der der Reiter gehört.
     * @param name
     *            Anzuzeigender Name des Reiters.
     * @param reaktor
     *            Objekt, das über das Schließen des Reiters informiert wird.
     * @param colorizer
     *            Objekt zum Einfärben der Komponente.
     * @param showCloseButton
     *            Gibt an, ob der Button zum Löschen angezeigt werden soll.
     */
    public Tabulator(String tabIdentifier, String name, CloseButtonReaktor reaktor,
            Colorizer colorizer, boolean showCloseButton) {

        /* Entfernen der im JPanel vorhandenen Abstände im FlowLayout: */
        super(new FlowLayout(FlowLayout.LEFT, 0, 0));

        this.tabIdentifier = tabIdentifier;
        this.name = name;
        this.colorizer = colorizer;
        this.showCloseButton = showCloseButton;
        changeName = true;

        setColors(this);
        initGui(reaktor);
    }

    private static CloseButtonReaktor createDoNothingCloseReaktor() {
        return new CloseButtonReaktor() {
            @Override
            public void closeButtonPressed(String tabUserOrGroupIdentifier) {
                // wir tun nichts...
            }};
    }

    /** Legt fest, dass der Name des Tabulators nicht geändert werden soll. */
    public void doNotChangeName() {
        changeName = false;
    }

    private void setColors(Component component) {
        if (null != colorizer) {
            colorizer.setColors(component);
        }
    }

    /**
     * Baut die kleine Gui des Reiterfähnchens auf.
     *
     * @param reaktor
     *            Objekt, das über das Schließen des Reiters informiert wird.
     */
    private void initGui(CloseButtonReaktor reaktor) {
        setOpaque(false);

        nameLabel = new JLabel();
        setColors(nameLabel);
        nameLabel.setText(name);
        add(nameLabel);

        nameLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));

        closeButton = new CloseTabButton(tabIdentifier, reaktor);
        setColors(closeButton);
        if (showCloseButton) {
            add(closeButton);
        }

        setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
    }

    /** Getter für den angezeigten Namen. */
    public String getTabulatorName() {
        return name;
    }

    /** Ändert den angezeigten Namen. */
    @Override
    public void updateName(String name) {
        if (changeName) {
            this.name = name;
            nameLabel.setText(name);
        }
    }

    /**
     * Färbt den Reiter so, dass auffällt, dass neue Nachrichten vorliegen oder die Datei geändert
     * ist.
     */
    @Override
    public void signChangedState() {
        if (null != originalForeground) { // nur 1. Mal, sonst rot!
            originalForeground = nameLabel.getForeground(); // ist bei mir wirklich BLACK.
        }
        nameLabel.setForeground(Color.RED);
        nameLabel.validate();
    }

    /** Färbt den Reiter normal. */
    @Override
    public void signUnchangedState() {
        if (null != colorizer) {
            setColors(nameLabel);
        }
        else if (null != originalForeground) {
            nameLabel.setForeground(originalForeground);
        }
        else  {
            nameLabel.setForeground(Color.BLACK);
        }
        nameLabel.validate();
    }

    /**
     * Da der ActionListener entfernt wird, wenn der Close-Button gedrückt wird, muss wieder ein
     * solcher installiert werden, wenn das zugehörige Gespräch wieder aktiviert wird.
     */
    public void reactivate() {
        closeButton.reactivate();
    }

    @Override
    public String toString() {
        return "Tabulator [tabIdentifier=" + tabIdentifier + ", name=" + name + "]";
    }

}
