/*
 * #%L
 * gitools-ui-platform
 * %%
 * Copyright (C) 2013 Universitat Pompeu Fabra - Biomedical Genomics group
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public 
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/gpl-3.0.html>.
 * #L%
 */
package org.gitools.ui.platform.imageviewer;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * A component for displaying a series of images. Supports paging through GUI as well as setting the current
 * position via function {@link #setPosition(int)}. When the position is changed, the {@link #positionChanged()}
 * method is called. Subclasses should override this method to update the image according to the new position.
 *
 * @author Kazó Csaba
 */
public class ImageSequenceViewer {

    private final ImageViewer imageViewer;
    private int number, position;
    private JButton forwardButton, backwardButton;
    private JLabel locationLabel;

    private JPanel panel = new JPanel(new BorderLayout()) {
        /**
         * Overridden to call {@link #positionChanged()}.
         */
        @Override
        public void addNotify() {
            super.addNotify();
            positionChanged();
        }
    };

    /**
     * Creates a new sequence viewer that can display the specified number of images.
     *
     * @param number the number of images
     * @throws IllegalArgumentException if the number is negative
     */
    public ImageSequenceViewer(int number) {
        this(number, 0);
    }

    /**
     * Creates a new sequence viewer that can display the specified number of images.
     *
     * @param number   the number of images
     * @param startPos the initial position of the viewer
     * @throws IllegalArgumentException if the number is negative or the starting position is not valid
     */
    public ImageSequenceViewer(int number, int startPos) {
        if (number <= 0 || startPos < 0 || startPos >= number)
            throw new IllegalArgumentException();
        imageViewer = new ImageViewer();
        this.number = number;
        this.position = startPos;

        panel.add(imageViewer.getComponent(), BorderLayout.CENTER);

        forwardButton = new JButton(">");
        backwardButton = new JButton("<");
        JPanel locationPanel = new JPanel(new FlowLayout());
        locationPanel.add(backwardButton);
        locationPanel.add(createLocationDefinition());
        locationPanel.add(forwardButton);

        forwardButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                setPosition(position + 1);
            }
        });
        backwardButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                setPosition(position - 1);
            }
        });

        panel.add(locationPanel, BorderLayout.NORTH);

        setPosition(position);
    }

    /**
     * Returns the Swing component for this sequence viewer.
     *
     * @return the component
     */
    public JComponent getComponent() {
        return panel;
    }

    /**
     * Called when the current position of the viewer has changed. The default implementation does nothing.
     * Subclasses should override this method to update the image.
     * <p/>
     * This method is not called from the constructor, but it is called before the viewer is made visible,
     * so subclasses can safely use this method to set the initial image.
     */
    protected void positionChanged() {
    }

    public ImageViewer getImageViewer() {
        return imageViewer;
    }

    /**
     * Sets the position of the viewer.
     *
     * @param pos the new position of the viewer
     * @throws IllegalArgumentException if the position is not valid
     */
    public void setPosition(int pos) {
        if (pos < 0 || pos >= number)
            throw new IllegalArgumentException("Position " + pos + " out of range");
        position = pos;
        updateLocationDefinition(position);
        forwardButton.setEnabled(position < number - 1);
        backwardButton.setEnabled(position > 0);
        if (panel.getParent() != null) positionChanged();
    }

    /**
     * Returns the current position of this image sequence shower.
     */
    public int getPosition() {
        return position;
    }

    /**
     * Creates and returns the component that displays the current position to the user. The default implementation
     * creates a <code>JLabel</code>.
     *
     * @return the location component
     */
    protected JComponent createLocationDefinition() {
        locationLabel = new JLabel();
        return locationLabel;
    }

    /**
     * Called when the current position changes to update the location component.
     *
     * @param pos the current position
     */
    protected void updateLocationDefinition(int pos) {
        locationLabel.setText(String.format("%d/%d", pos + 1, number));
    }
}
