package de.renew.navigator.gui;

import java.awt.Component;
import java.awt.Image;
import java.util.LinkedList;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeCellRenderer;

import CH.ifa.draw.util.Iconkit;
import de.renew.navigator.models.TreeElement;

/**
 * FileTreeCellRenderer class.
 *
 * @version 2015-10-14
 */
public abstract class FileTreeCellRenderer implements TreeCellRenderer {
    private static final int ICON_SIZE = 16;

    private final LinkedList<FileTreeCellRenderer> _additionalRenderers;
    private final DefaultTreeCellRenderer _cellRenderer;

    /**
     * Default constructor.
     */
    public FileTreeCellRenderer() {
        _additionalRenderers = new LinkedList<>();
        _cellRenderer = new DefaultTreeCellRenderer();
    }

    /**
     * Renders the tree cell.
     *
     * @param target the target renderer
     * @param element the tree element
     * @param selected whether the cell is selected
     * @param expanded whether the cell is expanded
     */
    public abstract void render(
        DefaultTreeCellRenderer target, TreeElement element, boolean selected, boolean expanded);

    @Override
    public final Component getTreeCellRendererComponent(
        JTree tree, Object value, boolean sel, boolean exp, boolean leaf, int row, boolean hasFocus)
    {
        _cellRenderer.getTreeCellRendererComponent(tree, value, sel, exp, leaf, row, hasFocus);
        _cellRenderer.setFont(tree.getFont());

        if (!(value instanceof FileTreeNode)) {
            return _cellRenderer;
        }

        final TreeElement element = ((FileTreeNode) value).getModel();
        render(_cellRenderer, element, sel, exp);

        for (FileTreeCellRenderer renderer : _additionalRenderers) {
            renderer.render(_cellRenderer, element, sel, exp);
        }

        return _cellRenderer;
    }

    /**
     * Adds an additional renderer.
     *
     * @param additionalRenderer the additional renderer
     */
    public void addAdditionalRenderer(FileTreeCellRenderer additionalRenderer) {
        this._additionalRenderers.add(additionalRenderer);
    }

    /**
     * Removes an additional renderer.
     *
     * @param additionalRenderer the additional renderer
     */
    public void removeAdditionalRenderer(FileTreeCellRenderer additionalRenderer) {
        this._additionalRenderers.remove(additionalRenderer);
    }

    /**
     * Uses the icon kit to load an image from its filename.
     *
     * @param filename the name of the file
     * @return the loaded icon
     */
    protected static Icon loadIcon(String filename) {
        return new ImageIcon(
            Iconkit.instance().loadImage(filename)
                .getScaledInstance(ICON_SIZE, ICON_SIZE, Image.SCALE_SMOOTH));
    }

    /**
     * Applies the icon to the label.
     *
     * @param label the label to apply the icon to
     * @param filename the name of the file
     */
    protected static void applyIcon(JLabel label, String filename) {
        label.setIcon(loadIcon(filename));
    }
}