package de.duehl.swing.text.html.characteristic;

/*
 * Copyright 2021 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 static de.duehl.swing.ui.colors.ColorTool.getHexColorByName;
import static de.duehl.swing.ui.colors.NamedColorListFabric.*;

import java.util.Objects;
import java.util.Properties;

import de.duehl.basics.text.handling.BooleanHandling;

/**
 * Diese Klasse stellt die Eigenschaften eines Stücks Text dar, welcher in einem HTML-Editor
 * eingefärbt dargestellt wird.
 *
 * @version 1.01     2021-12-15
 * @author Christian Dühl
 */

public class OpticalTextPartCharacteristic {

    private static final String FOREGROUND_PROPERTY_NAME = "foregroundHexColor";
    private static final String BACKGROUND_PROPERTY_NAME = "backgroundHexColor";
    private static final String USE_BACKGROUND_PROPERTY_NAME = "useBackgroundHexColor";
    private static final String BOLD_PROPERTY_NAME = "bold";
    private static final String ITALIC_PROPERTY_NAME = "italic";
    private static final String UNDERLINE_PROPERTY_NAME = "underline";

    /** Die Vordergrundfarbe des Textes für HTML im Format "ff0000". */
    private String foregroundHexColor;

    /** Die Hintergrundfarbe des Textes für HTML im Format "ff0000". */
    private String backgroundHexColor;

    /** Gibt an, ob die Hintergrundfarbe benutzt wird. */
    private boolean useBackgroundColor;

    /** Gibt an, ob der Text fett dargestellt wird. */
    private boolean bold;

    /** Gibt an, ob der Text kursiv dargestellt wird. */
    private boolean italic;

    /** Gibt an, ob der Text unterstrichen dargestellt wird. */
    private boolean underline;

    /** Konstruktor. */
    public OpticalTextPartCharacteristic() {
        foregroundHexColor = getHexColorByName(BLACK);
        backgroundHexColor = getHexColorByName(WHITE);
        useBackgroundColor = false;

        bold = false;
        italic = false;
        underline = false;
    }

    /** Copy-Konstruktor. */
    public OpticalTextPartCharacteristic(OpticalTextPartCharacteristic that) {
        copyFrom(that);
    }

    /** Übernimmt die Darstellungseigenschaften aus einem anderen Objekt. */
    public void copyFrom(OpticalTextPartCharacteristic source) {
        foregroundHexColor = source.foregroundHexColor;
        backgroundHexColor = source.backgroundHexColor;
        useBackgroundColor = source.useBackgroundColor;
        bold = source.bold;
        italic = source.italic;
        underline = source.underline;
    }

    /** Getter für die Vordergrundfarbe des Textes für HTML im Format "ff0000". */
    public String getForegroundHexColor() {
        return foregroundHexColor;
    }

    /** Setter für die Vordergrundfarbe des Textes für HTML im Format "ff0000". */
    public void setForegroundHexColor(String foregroundHexColor) {
        this.foregroundHexColor = foregroundHexColor;
    }

    /** Getter für die Hintergrundfarbe des Textes für HTML im Format "ff0000". */
    public String getBackgroundHexColor() {
        return backgroundHexColor;
    }

    /** Setter für die Hintergrundfarbe des Textes für HTML im Format "ff0000". */
    public void setBackgroundHexColor(String backgroundHexColor) {
        this.backgroundHexColor = backgroundHexColor;
    }

    /** Gibt an, ob die Hintergrundfarbe benutzt wird. */
    public boolean isUseBackgroundColor() {
        return useBackgroundColor;
    }

    /** Legt fest, ob die Hintergrundfarbe benutzt wird. */
    public void setUseBackgroundColor(boolean useBackgroundColor) {
        this.useBackgroundColor = useBackgroundColor;
    }

    /** Gibt an, ob der Text fett dargestellt wird. */
    public boolean isBold() {
        return bold;
    }

    /** Legt fest, ob der Text fett dargestellt wird. */
    public void setBold(boolean bold) {
        this.bold = bold;
    }

    /** Gibt an, ob der Text kursiv dargestellt wird. */
    public boolean isItalic() {
        return italic;
    }

    /** Legt fest, ob der Text kursiv dargestellt wird. */
    public void setItalic(boolean italic) {
        this.italic = italic;
    }

    /** Gibt an, ob der Text unterstrichen dargestellt wird. */
    public boolean isUnderline() {
        return underline;
    }

    /** Legt fest, ob der Text unterstrichen dargestellt wird. */
    public void setUnderline(boolean underline) {
        this.underline = underline;
    }

    /** Erzeugt den öffnenden HTML-Span mit dem Stil passend zu den Eigenschaften. */
    public String createOpeningSpan() {
        return "<span style=\"" + createHtmlStyle() + "\">";
    }

    /** Erzeugt den Stil für HTML-Tags passend zu den Eigenschaften. */
    public String createHtmlStyle() {
        StringBuilder builder = new StringBuilder();

        builder.append("color:").append(foregroundHexColor);

        if (useBackgroundColor) {
            builder.append(";background-color:").append(backgroundHexColor);
        }
        if (bold) {
            builder.append(";font-weight:bold");
        }
        if (italic) {
            builder.append(";font-style:italic");
        }
        if (underline) {
            builder.append(";text-decoration:underline");
        }

        return builder.toString();
    }

    /**
     * Lädt die Eigenschaften aus einem Properties-Objekt der Persistenz.
     *
     * @param properties
     *            Die persistenten Eigenschaften, in denen die Eigenschaften dieses
     *            OpticalTextPartCharacteristic-Objekts abgelegt werden sollen.
     * @param keyPart
     *            Erster Teil des Namens des Schlüssels in den die Eigenschaften dieses
     *            OpticalTextPartCharacteristic-Objekts abgelegt werden sollen (z.B. "options").
     * @param keyPart
     *            Mittlerer Teil des Namens des Schlüssels in den die Eigenschaften dieses
     *            OpticalTextPartCharacteristic-Objekts abgelegt werden sollen (z.b.
     *            "foregroundHexColor").
     */
    public void loadCharacteristicsFromProperties(Properties properties, String frontKeyPart,
            String middleKeyPart) {
        {
            String key = createFullPropertyName(frontKeyPart, middleKeyPart, FOREGROUND_PROPERTY_NAME);
            if (properties.containsKey(key)) {
                String foregroundHexColor = properties.getProperty(key);
                setForegroundHexColor(foregroundHexColor);
            }
        }
        {
            String key = createFullPropertyName(frontKeyPart, middleKeyPart,
                    BACKGROUND_PROPERTY_NAME);
            if (properties.containsKey(key)) {
                String backgroundHexColor = properties.getProperty(key);
                setBackgroundHexColor(backgroundHexColor);
            }
        }
        {
            String key = createFullPropertyName(frontKeyPart, middleKeyPart,
                    USE_BACKGROUND_PROPERTY_NAME);
            if (properties.containsKey(key)) {
                String useBackgroundHexColorAsString = properties.getProperty(key);
                boolean useBackgroundHexColor = BooleanHandling.stringToBoolean(
                        useBackgroundHexColorAsString);
                setUseBackgroundColor(useBackgroundHexColor);
            }
        }
        {
            String key = createFullPropertyName(frontKeyPart, middleKeyPart, BOLD_PROPERTY_NAME);
            if (properties.containsKey(key)) {
                String boldAsString = properties.getProperty(key);
                boolean bold = BooleanHandling.stringToBoolean(boldAsString);
                setBold(bold);
            }
        }
        {
            String key = createFullPropertyName(frontKeyPart, middleKeyPart, ITALIC_PROPERTY_NAME);
            if (properties.containsKey(key)) {
                String italicAsString = properties.getProperty(key);
                boolean italic = BooleanHandling.stringToBoolean(italicAsString);
                setItalic(italic);
            }
        }
        {
            String key = createFullPropertyName(frontKeyPart, middleKeyPart,
                    UNDERLINE_PROPERTY_NAME);
            if (properties.containsKey(key)) {
                String underlineAsString = properties.getProperty(key);
                boolean underline = BooleanHandling.stringToBoolean(underlineAsString);
                setUnderline(underline);
            }
        }
    }

    /**
     * Speichert die Eigenschaften in einem Properties-Objekt der Persistenz ab.
     *
     * @param properties
     *            Die persistenten Eigenschaften, in denen die Eigenschaften dieses
     *            OpticalTextPartCharacteristic-Objekts abgelegt werden sollen.
     * @param keyPart
     *            Erster Teil des Namens des Schlüssels in den die Eigenschaften dieses
     *            OpticalTextPartCharacteristic-Objekts abgelegt werden sollen (z.B. "options").
     * @param keyPart
     *            Mittlerer Teil des Namens des Schlüssels in den die Eigenschaften dieses
     *            OpticalTextPartCharacteristic-Objekts abgelegt werden sollen (z.b.
     *            "foregroundHexColor").
     */
    public void saveCharacteristicsToProperties(Properties properties, String frontKeyPart,
            String middleKeyPart) {
        properties.setProperty(
                createFullPropertyName(frontKeyPart, middleKeyPart, FOREGROUND_PROPERTY_NAME),
                getForegroundHexColor());
        properties.setProperty(
                createFullPropertyName(frontKeyPart, middleKeyPart, BACKGROUND_PROPERTY_NAME),
                getBackgroundHexColor());
        properties.setProperty(
                createFullPropertyName(frontKeyPart, middleKeyPart, USE_BACKGROUND_PROPERTY_NAME),
                BooleanHandling.booleanToString(isUseBackgroundColor()));
        properties.setProperty(
                createFullPropertyName(frontKeyPart, middleKeyPart, BOLD_PROPERTY_NAME),
                BooleanHandling.booleanToString(isBold()));
        properties.setProperty(
                createFullPropertyName(frontKeyPart, middleKeyPart, ITALIC_PROPERTY_NAME),
                BooleanHandling.booleanToString(isItalic()));
        properties.setProperty(
                createFullPropertyName(frontKeyPart, middleKeyPart, UNDERLINE_PROPERTY_NAME),
                BooleanHandling.booleanToString(isUnderline()));
    }

    String createFullPropertyName(String frontKeyPart, String middleKeyPart, String detailPart) {
        return frontKeyPart + "." + middleKeyPart + "." + detailPart;
    }

    /** Erzeugt eine Kopie dieses Objekts mit den gleichen Daten. */
    public OpticalTextPartCharacteristic copy() {
        OpticalTextPartCharacteristic copy = new OpticalTextPartCharacteristic();
        copy.foregroundHexColor = foregroundHexColor;
        copy.backgroundHexColor = backgroundHexColor;
        copy.useBackgroundColor = useBackgroundColor;
        copy.bold = bold;
        copy.italic = italic;
        copy.underline = underline;

        return copy;
    }

    @Override
    public String toString() {
        return "OpticalTextPartCharacteristic [bold=" + bold + ", italic=" + italic + ", underline="
                + underline + ", foregroundHexColor=" + foregroundHexColor + ", backgroundHexColor="
                + backgroundHexColor + ", useBackgroundColor=" + useBackgroundColor + "]";
    }

    @Override
    public int hashCode() {
        return Objects.hash(backgroundHexColor, bold, foregroundHexColor, italic, underline,
                useBackgroundColor);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        OpticalTextPartCharacteristic other = (OpticalTextPartCharacteristic) obj;
        return Objects.equals(backgroundHexColor, other.backgroundHexColor) && bold == other.bold
                && Objects.equals(foregroundHexColor, other.foregroundHexColor)
                && italic == other.italic && underline == other.underline
                && useBackgroundColor == other.useBackgroundColor;
    }

}
