package CH.ifa.draw.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ContainerAdapter;
import java.awt.event.ContainerEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Set;
import javax.imageio.ImageIO;
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JToggleButton;

import bibliothek.gui.DockUI;
import bibliothek.gui.dock.util.laf.LookAndFeelColors;

import de.renew.plugin.PluginManager;
import de.renew.windowmanagement.DraggableComponentDropTarget;

/**
 * ToolButtonContainer contains ToolButtons that can be dragged and dropped within its confines.
 * @deprecated This class is not to be used externally and will later be hidden.
 */
@Deprecated
public class ToolButtonContainer extends JPanel implements DraggableComponentDropTarget {

    private final static String IMAGES = "CH/ifa/draw/images/";
    /**
     * Set of buttons that will be part of this container.
     */
    private final Set<AbstractButton> _buttons;
    /**
     * Palette of buttons that will be part of this container.
     */
    private static final org.apache.log4j.Logger LOGGER =
        org.apache.log4j.Logger.getLogger(ToolButtonContainer.class);

    private ToolButtonPalette _palette;
    /**
     * Title bar of this container, will have the close and hide button for this container.
     */
    private JPanel _titleBar;

    /**
     * Constructor that takes a set of buttons that will be part of the container.
     * @param buttons a set of buttons that will be part of the container
     */
    public ToolButtonContainer(Set<AbstractButton> buttons) {

        _buttons = buttons;
        createPalette();
        createTitleBar();

        this.setLayout(new BorderLayout());
        this.add(_titleBar, BorderLayout.NORTH);
        this.add(_palette, BorderLayout.CENTER);
    }

    private JToggleButton createHideToolsButton() {

        JToggleButton button = new JToggleButton();
        button.setIcon(new ImageIcon(loadImage(IMAGES + "toolbuttons_hid.png")));
        button.setSelectedIcon(new ImageIcon(loadImage(IMAGES + "toolbuttons_open.png")));
        button.setToolTipText("Show/Hide tools");
        button.setSelected(true);
        button.addActionListener(e -> {
            boolean newState = !_palette.isVisible();
            _palette.setVisible(newState);
        });
        return button;

    }

    private JButton createCloseButton() {

        JButton button = new JButton();
        button.setIcon(new ImageIcon(loadImage(IMAGES + "toolbuttons_close.png")));
        final ToolButtonContainer container = this;
        button.addActionListener(e -> {
            Container parent = container.getParent();
            if (parent != null) {
                parent.remove(container);
                parent.revalidate();
            }

        });
        button.setToolTipText("Close Tools");
        return button;
    }

    private void createPalette() {

        _palette = new ToolButtonPalette();
        int minWidth = 35;
        for (AbstractButton button1 : _buttons) {
            _palette.add(button1);
            int tempWidth = button1.getIcon().getIconWidth();
            if (minWidth < tempWidth) {
                minWidth = tempWidth;
            }
        }
        int maxWidth = 50 < minWidth ? minWidth * 2 : 50;


        _palette.setLayout(new ToolPanelLayout(minWidth, maxWidth));
        //_palette.setVisible(false);

        // Remove this component if the palette is empty.
        final ToolButtonContainer container = this;
        _palette.addContainerListener(new ContainerAdapter() {
            @Override
            public void componentRemoved(ContainerEvent e) {
                if (_palette.getComponentCount() == 0) {
                    Container parent = container.getParent();
                    if (parent != null) {
                        parent.remove(container);
                        parent.revalidate();
                    }
                }
            }
        });
    }

    private void createTitleBar() {

        createHideToolsButton();
        createCloseButton();
        _titleBar = new JPanel() {

            @Override
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                Color background = DockUI.getColor(LookAndFeelColors.TITLE_SELECTION_BACKGROUND);
                Color light = DockUI.getColor(LookAndFeelColors.TITLE_BACKGROUND);

                Graphics2D g2 = (Graphics2D) g;
                GradientPaint backgroundPaint =
                    new GradientPaint(0, 0, background, getWidth(), getHeight(), light);
                g2.setPaint(backgroundPaint);
                g2.fill(new Rectangle(0, 0, getWidth(), getHeight()));
            }
        };
        _titleBar.setLayout(new BorderLayout());
        _titleBar.add(createHideToolsButton(), BorderLayout.WEST);
        _titleBar.add(createCloseButton(), BorderLayout.EAST);
        _titleBar.setBorder(BorderFactory.createLoweredSoftBevelBorder());
    }

    /**
     * Gets all buttons that are associated with this ToolButtonContainer as an array.
     * @return buttons that are part of this ToolButtonContainer as an array
     */
    protected Component[] getButtons() {

        return _palette.getComponents();
    }

    @Override
    public void dropComponent(Component draggedComponent, Point locationOnScreen) {
        if (_palette.isShowing()) {
            _palette.dropComponent(draggedComponent, locationOnScreen);
        }
    }

    private static class ToolButtonPalette extends JPanel implements DraggableComponentDropTarget {


        @Override
        public void dropComponent(Component draggedComponent, Point locationOnScreen) {

            if (draggedComponent instanceof AbstractButton) {
                Point thisLocation = this.getLocationOnScreen();
                Point adjustedLocation = new Point(
                    locationOnScreen.x - thisLocation.x, locationOnScreen.y - thisLocation.y);

                Component target = getComponentAt(adjustedLocation);
                int index = 0;
                int count = getComponentCount();

                for (int i = 0; i < count; i++) {
                    if (getComponent(i) == target) {
                        index = i;
                        break;
                    }
                }

                add(draggedComponent, index);
            }
        }
    }

    /**
     * Tries to load an image from a pathname.
     * Used for later creating icon images.
     */
    private BufferedImage loadImage(final String path) {

        URL url = PluginManager.getInstance().getBottomClassLoader().getResource(path);
        if (url == null) {
            File file = new File(path);
            try {
                url = file.toURI().toURL();
            } catch (MalformedURLException e) {
                LOGGER.error("URL is not valid" + e);
            }
        }
        if (url != null) {
            try {
                return ImageIO.read(url);
            } catch (IOException e) {
                LOGGER.error("Reading from URL failed" + e);
            }
        }

        return null;
    }
}
