package com.jidesoft.icons;

import javax.swing.*;
import java.awt.*;
import java.util.HashMap;
import java.util.Map;

/**
 * <code>IconSetManager</code> contains all the JIDE icon sets in one class so that you can access all of them from one
 * single place and switch to different icon set just by calling {@link #setActiveIconSetName(String)}.
 * <p/>
 * In order to use IconSetManager, you need to define and register the JIDE icon set first. You can do something like
 * this.
 * <code><pre>
 * public static IconSetManager ICON_SET_MANAGER = new IconSetManager();
 * <p/>
 * static {
 *      ICON_SET_MANAGER.add("vista", new int[]{16, 24, 32, 48, 64, 96, 128, 256}, "/com/jidesoft/icons/vista");
 *      ICON_SET_MANAGER.add("xp", new int[]{16, 24, 32, 48, 64}, "/com/jidesoft/icons/xp");
 *      // add more if you have. Right now JIDE only provides one icon set but we will add more
 * }
 * </pre></code>
 * Later on if you want to use it, for example, to get a File-New icon, you just call
 * <code><pre>
 * ICON_SET_MANAGER.getImageIcon(IconSet.File.NEW, size);
 * </pre></code>
 * The size is the size you want such as 16, 24, 32, 48, or 64 depending on what sizes are available.
 */
public class IconSetManager {
    private Map<String, IconSet> _availableStyles;
    private String _activeIconSetName = null;
    private IconSet _activeIconSet = null;

    /**
     * finds the icon set if it is available.
     *
     * @param iconSetName the icon set name
     *
     * @return the icon set. Null if not found.
     */
    public IconSet findIconSet(String iconSetName) {
        if (_availableStyles == null) {
            return null;
        }
        return _availableStyles.get(iconSetName);
    }

    /**
     * Gets the active icon set name. The active icon set will be used when you call {@link #getImageIcon(String)}
     * method.
     *
     * @return the active icon set name.
     */
    public String getActiveIconSetName() {
        return _activeIconSetName;
    }

    /**
     * gets the active icon set.
     *
     * @return the active icon set.
     */
    public IconSet getActiveIconSet() {
        return _activeIconSet;
    }

    public void add(String name, int[] sizes, String packageName) {
        if (_availableStyles == null) {
            _availableStyles = new HashMap<String, IconSet>();
        }
        _availableStyles.put(name, new IconSet(name, sizes, packageName));
        if (_availableStyles.size() == 1) {
            setActiveIconSetName(name);
        }
    }

    public void remove(String name) {
        if (_availableStyles != null) {
            _availableStyles.remove(name);
        }
    }

    /**
     * Sets the active icon set name. If the icon set is not found, IllegalArgumentException will be thrown.
     *
     * @param activeIconSetName the new active icon set name.
     *
     * @throws IllegalArgumentException if the icon set is not found by that name.
     */
    public void setActiveIconSetName(String activeIconSetName) {
        IconSet iconSet = findIconSet(activeIconSetName);
        if (iconSet == null) {
            throw new IllegalArgumentException("Icon set \"" + activeIconSetName + "\" not found");
        }
        _activeIconSet = iconSet;
        _activeIconSetName = activeIconSetName;
    }

    /**
     * Gets the ImageIcon.
     *
     * @param iconName the icon name as defined in IconSet.
     *
     * @return the ImageIcon.
     */
    public ImageIcon getImageIcon(String iconName) {
        return getImageIcon(iconName, 16);
    }

    /**
     * Gets the ImageIcon.
     *
     * @param iconName the icon name as defined in IconSet.
     * @param size     the icon size. If the size is not available, it will find the closest size that is larger than
     *                 the requested size.
     *
     * @return the ImageIcon.
     */
    public ImageIcon getImageIcon(String iconName, int size) {
        String packageName = _activeIconSet.getPackageName();
        int actualSize = _activeIconSet.getNextAvailableSize(size);
        String fullIconName = packageName + "/png/" + actualSize + "x" + actualSize + "/" + iconName;
        ImageIcon icon = IconsFactory.getImageIcon(IconSetManager.class, fullIconName);
        if (actualSize == size) {
            return icon;
        }
        else {
            return IconsFactory.getScaledImage(null, icon, size, size);
        }
    }

    /**
     * Gets the ImageIcon.
     *
     * @param iconName        the icon name as defined in IconSet.
     * @param size            the icon size. If the size is not available, it will find the closest size that is larger
     *                        than the requested size.
     * @param overlayIconName the overlay icon name as defined in IconSet.
     * @param location        the location as defined in SwingConstants - CENTER, NORTH, SOUTH, WEST, EAST, NORTH_EAST,
     *                        NORTH_WEST, SOUTH_WEST and SOUTH_EAST.
     *
     * @return the ImageIcon.
     */
    public ImageIcon getOverlayImageIcon(String iconName, int size, String overlayIconName, int location) {
        return getOverlayImageIcon(iconName, size, overlayIconName, location, new Insets(0, 0, 0, 0));
    }

    /**
     * Gets the ImageIcon with an overlay icon on it.
     *
     * @param iconName        the icon name as defined in IconSet.
     * @param size            the icon size. If the size is not available, it will find the closest size that is larger
     *                        than the requested size.
     * @param overlayIconName the overlay icon name as defined in IconSet. The icons in the Overlay category are half
     *                        the size of the regular icons. So this method will take the middle portion of the overlay
     *                        icon specified in the overlayIconName and use it as the overlay icon.
     * @param location        the location as defined in SwingConstants - CENTER, NORTH, SOUTH, WEST, EAST, NORTH_EAST,
     *                        NORTH_WEST, SOUTH_WEST and SOUTH_EAST.
     * @param insets          the margin of the overlay icon to the border of the icon.
     *
     * @return the ImageIcon.
     */
    public ImageIcon getOverlayImageIcon(String iconName, int size, String overlayIconName, int location, Insets insets) {
        ImageIcon icon = getImageIcon(iconName, size);
        if (icon == null) {
            return null;
        }
        ImageIcon overlay = getImageIcon(overlayIconName, size);
        if (overlay == null) {
            return icon;
        }

        // grab the middle portion of the overlay icon only
        overlay = IconsFactory.getIcon(null, overlay, size / 4, size / 4, size / 2, size / 2);

        return IconsFactory.getOverlayIcon(null, icon, overlay, location, insets);
    }

    /**
     * Gets the ImageIcon with an overlay icon on it.
     *
     * @param iconName        the icon name as defined in IconSet.
     * @param size            the icon size. If the size is not available, it will find the closest size that is larger
     *                        than the requested size.
     * @param overlayIconName the overlay icon name as defined in IconSet. The overlay icon doesn't have to be in the
     *                        overlay category. It can be any regular icon. Of course the size of the overlay icon
     *                        should be smaller than the size of the regular icon.
     * @param overlayIconSize the size of the overlay icon.
     * @param location        the location as defined in SwingConstants - CENTER, NORTH, SOUTH, WEST, EAST, NORTH_EAST,
     *                        NORTH_WEST, SOUTH_WEST and SOUTH_EAST.
     * @param insets          the margin of the overlay icon to the border of the icon.
     *
     * @return the ImageIcon.
     */
    public ImageIcon getOverlayImageIcon(String iconName, int size, String overlayIconName, int overlayIconSize, int location, Insets insets) {
        ImageIcon icon = getImageIcon(iconName, size);
        if (icon == null) {
            return null;
        }
        ImageIcon overlay = getImageIcon(overlayIconName, overlayIconSize);
        if (overlay == null) {
            return icon;
        }

        return IconsFactory.getOverlayIcon(null, icon, overlay, location, insets);
    }

//    public static void main(String[] args) {
//        IconSetManager manager = new IconSetManager();
//        manager.add("xp", new int[]{16, 24, 32, 48, 64}, "/com/jidesoft/icons/xp");
//        JFrame frame = new JFrame();
//        frame.add(new JLabel(manager.getImageIcon(IconSet.Direction.BOTTOM, 64)));
//        frame.pack();
//        frame.setVisible(true);
//    }
}
