package de.duehl.swing.ui.colors;

/*
 * Copyright 2022 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 de.duehl.basics.text.NumberString;

/**
 * Diese Klasse bietet Methoden zum Übersetzen von Farben von ihrer hexadezimalen Stringdarstellung
 * in eine Swing-Farbe und zurück und aus Namen benannter Farben heraus sowohl in ihre
 * hexadezimalen Stringdarstellung als auch in eine Swing-Farbe.
 *
 * @version 1.01     2022-05-06
 * @author Christian Dühl
 */

public class ColorTranslator {

    /** Liste mit den benannten Farben. */
    private final NamedColorList namedColors;

    /** Konstruktor. */
    public ColorTranslator( ) {
        namedColors = new NamedColorListFabric().genrateColorList();
    }

    /**
     * Übersetzt eine Farbe in hexadezimalen Stringdarstellung in der Form
     * "FF0000" in eine Swing-Farbe.
     *
     * @param hexColor
     *            Farbe in hexadezimalen Stringdarstellung.
     * @return Swing-Farbe.
     * @throws UnknownColorException
     *             Wenn die hexadezimalen Stringdarstellung keine sechs Stellen
     *             hat oder der Zahlenwert nicht zur Basis 16 umgerechnet werden
     *             konnte.
     */
    public static Color hex2Swing(String hexColor) {
        if (hexColor.length() != 6) {
            throw new UnknownColorException("Der Farbwert der hexColor muss "
                    + "sechs Zeichen lang sein. Zum Beispiel \"FF0000\"! "
                    + "hexColor = '" + hexColor + "'");
        }

        int colorValue;
        try {
            colorValue = Integer.parseInt(hexColor, 16);
        }
        catch (NumberFormatException exception) {
            throw new UnknownColorException("Der Wert der hexColor konnte "
                    + "nicht zur Basis 16 in eine Integerzahl geparst "
                    + "werden. hexColor = " + hexColor);
        }
        Color color = new Color(colorValue);

        return color;
    }

    /**
     * Bildet aus einer Swing-Farbe eine Farbe in hexadezimalen
     * Stringdarstellung in der Form "FF0000".
     *
     * @param color
     *            Java-Farbe (etwa Color.RED).
     * @return HTML-Farbwert (etwa "FF0000").
     */
    public static String swing2Hex(Color color) {
        int red   = color.getRed();
        int green = color.getGreen();
        int blue  = color.getBlue();

        String redHex   = String.format("%02X", red);
        String greenHex = String.format("%02X", green);
        String blueHex  = String.format("%02X", blue);

        String result = redHex + greenHex + blueHex;
        return result;
    }

    /**
     * Getter für eine Swing-Farbe über ihren Namen.
     *
     * @param name
     *            Name der Farbe.
     * @return Swing-Farbe oder null, falls keine Farbe unter diesem Namen
     *         bekannt war.
     */
    public Color getColorByName(String name) {
        return namedColors.getColorByName(name);
    }

    /**
     * Getter für die hexadezimale Stringdarstellung einer Farbe über ihren
     * Namen.
     *
     * @param name
     *            Name der Farbe.
     * @return Hexadezimale Stringdarstellung oder null, falls keine Farbe unter
     *         diesem Namen bekannt war.
     */
    public String getHexCodeByName(String name) {
        return namedColors.getHexCodeFromNamedColorByName(name);
    }

    /**
     * Übersetzt eine Farbe mit Namen oder hexadezimaler Darstellung in eine
     * Swing-Farbe.
     *
     * @param hexColorOrName
     *            Farbe dieses Eintrags (Name oder hexadezimal).
     * @return Swing-Farbe.
     */
    public Color nameOrHex2Swing(String hexColorOrName) {
        if (hexColorOrName.length() == 6
                && hexColorOrName.matches("[A-Fa-f0-9]{6}")) {
            return ColorTranslator.hex2Swing(hexColorOrName);
        }
        else {
            return getColorByName(hexColorOrName);
        }
    }

    /**
     * Bildet aus einem RGB Integer-Tripel einen HTML-Farbwert in der Form "FF0000".
     *
     * @param red
     *            Farbwert für rot als Integer zwischen 0 und 255.
     * @param green
     *            Farbwert für grün als Integer zwischen 0 und 255.
     * @param blue
     *            Farbwert für blau als Integer zwischen 0 und 255.
     * @return HTML-Farbwert (etwa "FF0000").
     */
    public static String rgbToHexColor(int red, int green, int blue) {
        if (red < 0 || red > 255
                || green < 0 || green > 255
                || blue < 0 || blue > 255) {
            throw new IllegalArgumentException("Parameter außerhalb des erlaubtenm Bereichs "
                    + "[0, 255]\n"
                    + "\t" + "red   = " + red + "\n"
                    + "\t" + "green = " + green + "\n"
                    + "\t" + "blue  = " + blue + "\n");
        }

        String redString = Integer.toHexString(red);
        String greenString = Integer.toHexString(green);
        String blueString = Integer.toHexString(blue);

        redString = NumberString.addLeadingZeroes(redString, 2);
        greenString = NumberString.addLeadingZeroes(greenString, 2);
        blueString = NumberString.addLeadingZeroes(blueString, 2);

        return redString + greenString + blueString;
    }

}
