package de.duehl.swing.ui.resources;

/*
 * Copyright 2016 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.Image;
import java.awt.Toolkit;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.swing.Icon;
import javax.swing.ImageIcon;

/**
 * Diese Klasse bietet Möglichkeiten, benannte Grafikdateien zu laden.
 * Anwendungsbeispiel siehe hr.messenger.ui.resources.IconDefinitions.
 *
 * @version 1.01     2016-12-20
 * @author Christian Dühl
 */

public class IconLoader {

    /**
     * Dieses Verzeichnis bietet sprechende Kürzel für die Namen von Bilddateien
     * (ohne Pfad). Es ist empfehlenswert, im anwendenden Programm diese
     * sprechenden Namen wiederum als Konstanten zu definieren in etwa so:         <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     static final String INSPECT = "INSPECT";                                <br><br>
     *
     * später kann dann im Programm per                                            <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     IconLoader iconloader = new IconLoader(..., PROGRAMM_IMAGE);            <br>&nbsp;&nbsp;&nbsp;&nbsp;
     *     iconloader.addPictureIdentifier(INSPECT, "ecke_inspizieren.gif");       <br><br>
     *
     * der Verweis eingetragen werden. Mit                                         <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     Icon icon = iconloader.load(INSPECT);                                   <br><br>
     *
     * kann dann das Bild geladen werden.
     */
    private final Map<String, String> pictureByIdentifier;

    /** Eine Klasse, bei der die Bilddateien liegen. */
    private final Class<?> clazz;

    /**
     * Kürzel für das Bild für das Programm. Dieses muss vorher per                <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     static final String PROGRAMM_IMAGE = "PROGRAM_IMAGE";                   <br><br>
     *
     * definiert und dem IconLoader per                                            <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     IconLoader iconloader = new IconLoader(..., PROGRAMM_IMAGE);            <br>&nbsp;&nbsp;&nbsp;&nbsp;
     *     iconloader.addPictureIdentifier(PROGRAMM_IMAGE, "ged24.jpg");           <br><br>
     *
     * bekannt gemacht werden. Mit                                                 <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     Image image = iconloader.loadProgramIconImage();                        <br><br>
     *
     * kann dann das Bild geladen werden.
     *
     */
    private final String programmImageIdentifier;

    /**
     * Konstruktor
     *
     * @param clazz
     *            Klasse, bei der die Resourcen liegen. Hierbei bietet es sich
     *            an, die Bilder in einem extra Verzeichnis unterzubringen,
     *            etwa src/ui/resources und dann dort eine Klasse anzulegen,
     *            die die Bilderkürzel der Form                                    <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *                static final String INSPECT = "INSPECT";                     <br><br>
     *
     *            enthält.
     * @param programmImageIdentifier
     *            Kürzel für das Bild zum Programm. Dieses sollte vorher per       <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *                static final String PROGRAMM_IMAGE = "PROGRAM_IMAGE";        <br><br>
     *
     *            definiert werden.
     */
    public IconLoader(Class<?> clazz, String programmImageIdentifier) {
        this.clazz = clazz;
        this.programmImageIdentifier = programmImageIdentifier;
        pictureByIdentifier = new HashMap<>();
    }

    /**
     * Fügt ein Kürzel für eine Bilddatei hinzu. Das Kürzel selbst sollte so
     * definitiert werden:                                                         <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     static final String INSPECT = "INSPECT";                                <br><br>
     *
     * Dann kann im Programm per                                                   <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     IconLoader iconloader = new IconLoader(..., PROGRAMM_IMAGE);            <br>&nbsp;&nbsp;&nbsp;&nbsp;
     *     iconloader.addPictureIdentifier(INSPECT, "ecke_inspizieren.gif");       <br><br>
     *
     * der Verweis eingetragen werden. Mit                                         <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     Icon icon = iconloader.loadIcon(INSPECT);                               <br><br>
     *
     * oder                                                                        <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     Image programImage = iconloader.loadImage(INSPECT);                     <br><br>
     *
     * kann schließlich das Bild geladen werden.
     *
     * @param pictureIdentifier
     *            Kürzel für das Bild.
     * @param pictureFileNameWithoutPath
     *            Name der Bilddatei ohne Pfad, also etwa
     *            "ecke_inspizieren.gif".
     */
    public void addPictureIdentifier(String pictureIdentifier, String pictureFileNameWithoutPath) {
        pictureByIdentifier.put(pictureIdentifier, pictureFileNameWithoutPath);
    }

    /**
     * Diese Methode lädt ein Bild zu einem Kürzel für dieses Bild. Das
     * Kürzel Dieses muss vorher per                                               <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     static final String INSPECT = "INSPECT";                                <br><br>
     *
     * definiert werden und kann dann per                                          <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     IconLoader iconloader = new IconLoader(..., PROGRAMM_IMAGE);            <br>&nbsp;&nbsp;&nbsp;&nbsp;
     *     iconloader.addPictureIdentifier(INSPECT, "ecke_inspizieren.gif");       <br><br>
     *
     * der Verweis eingetragen werden. Mit                                         <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     Icon icon = iconloader.loadIcon(INSPECT);                               <br><br>
     *
     * kann später das hinterlegte Bild geladen werden.
     *
     * @param pictureIdentifier
     *            Kürzel für das Bild.
     * @return Icon mit dem gewünschten Bild.
     */
    public Icon loadIcon(String pictureIdentifier) {
        URL url = getResource(pictureIdentifier);
        Icon icon = new ImageIcon(url);
        return icon;
    }

    /**
     * Gibt das Icon des Programms als Image zurück. Dafür sollte vorher
     * ein Kürzel auf die folgende Weise hinterlegt werden:                        <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     static final String PROGRAMM_IMAGE = "PROGRAM_IMAGE";                   <br><br>
     *
     * Bei der Erzeugung des IconLoaders wird dieses dann angegeben:               <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     IconLoader iconloader = new IconLoader(..., PROGRAMM_IMAGE);            <br><br>
     *
     * Mit                                                                         <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     Image image = iconloader.loadProgramIconImage();                        <br><br>
     *
     * kann dann das Bild geladen werden.
     */
    public Image loadProgramIconImage() {
        return loadImage(programmImageIdentifier);
    }

    /**
     * Diese Methode lädt ein Bild zu einem Kürzel für dieses Bild. Das
     * Kürzel Dieses muss vorher per                                               <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     static final String INSPECT = "INSPECT";                                <br><br>
     *
     * definiert werden und kann dann per                                          <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     IconLoader iconloader = new IconLoader(..., PROGRAMM_IMAGE);            <br>&nbsp;&nbsp;&nbsp;&nbsp;
     *     iconloader.addPictureIdentifier(INSPECT, "ecke_inspizieren.gif");       <br><br>
     *
     * der Verweis eingetragen werden. Mit                                         <br><br>&nbsp;&nbsp;&nbsp;&nbsp;
     *
     *     Image programImage = iconloader.loadImage(INSPECT);                     <br><br>
     *
     * kann schließlich das Bild geladen werden.
     *
     * @param pictureIdentifier
     *            Kürzel für das Bild.
     * @return Image mit dem gewünschten Bild.
     */
    public Image loadImage(String pictureIdentifier) {
        URL url = getResource(pictureIdentifier);
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        Image imgage = toolkit.createImage(url);

        return imgage;
    }

    /**
     * Lädt eine Resource (etwa ein Bild) über einen Dateinamen ohne Pfad bei der hinterlegten
     * Klasse.
     *
     * @param pictureIdentifier
     *            Kürzel für das Bild.
     * @return URL zu dem gewünschten Bild.
     * @throws RuntimeException
     *             Falls das Kürzel für das Bild unbekannt ist oder für den zum Kürzel hinterlegten
     *             Resourcenamen keine solche Resource bekannt ist.
     */
    private URL getResource(String pictureIdentifier) {
        if (!pictureByIdentifier.containsKey(pictureIdentifier)) {
            throw new RuntimeException("Das Kürzel '" + pictureIdentifier
                    + "' ist nicht bekannt!");
        }
        String pictureFileNameWithoutPath = pictureByIdentifier.get(pictureIdentifier);
        URL url = clazz.getResource(pictureFileNameWithoutPath);
        if (null == url) {
            throw new RuntimeException("Zum Kürzel '" + pictureIdentifier
                    + "' ist der Dateiname '" + pictureFileNameWithoutPath
                    + "' hinterlegt. Zu diesem wurde aber keine Resource gefunden!");
        }
        return url;
    }

}
