import java.awt.Container;
import java.awt.BorderLayout;
import java.awt.Insets;
import java.awt.FlowLayout;
import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JFileChooser;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JScrollBar;
import javax.swing.AbstractButton;
import javax.swing.JPanel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JToggleButton;
import javax.swing.BorderFactory;

import java.awt.event.WindowListener;
import java.awt.event.WindowEvent;
import java.awt.event.ComponentListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;


public class JP2ViewerWindow extends JFrame implements WindowListener, ActionListener,
                                                       ComponentListener, ImageWindow
{

  private final int BUTTON_OPEN    = 0;
  private final int BUTTON_REFRESH = 1;
  private final int BUTTON_ZOOM    = 2;
  private final int BUTTON_VIEW    = 3;

  private AbstractButton buttons[] = new AbstractButton[4];
  private String buttonCads[] = {"openFile", "refresh", "zoom", "view"};

  private ImagePanel imagePanel;

  private JFileChooser fileChooser;

  private JLabel statusTxt;
  private JTextField addressTxt;
  private JLabel bytesTransmittedLabel;

  private JScrollBar verticalScrollBar;
  private JScrollBar horizontalScrollBar;


  public JP2ViewerWindow() throws Exception
  {
    addWindowListener(this);
    addComponentListener(this);

    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

    ImageIcon imageIcon = (ImageIcon)ProyectoProperties.simpleImages.get("eye");
    setIconImage(imageIcon.getImage());

    fileChooser = new JFileChooser();
    fileChooser.setAcceptAllFileFilterUsed(false);
    CustomFileFilter filter = new CustomFileFilter();
    filter.addExtension("jp2");
    filter.addExtension("jpx");
    filter.addExtension("j2c");
    filter.setDescription("Imagen JPEG2000");
    fileChooser.setFileFilter(filter);

    setTitle("JPEG2000 Viewer");

    initComponents();

    setSize(400, 400);
    pack();

    setVisible(true);
  }

  // Método encargado de construir la interfaz.
  private void initComponents() throws Exception
  {
    Container contentPane = getContentPane();
    contentPane.setLayout(new BorderLayout());

    JPanel centerPanel = new JPanel();
    centerPanel.setLayout(new BorderLayout());
    centerPanel.setBorder(BorderFactory.createLoweredBevelBorder());
    contentPane.add(centerPanel, BorderLayout.CENTER);

    JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout());

    JPanel panelButton = new JPanel();
    panelButton.setLayout(new FlowLayout(FlowLayout.LEFT, 3, 3));

    for(int i = 0; i < buttons.length; i++) {
      if(i == BUTTON_ZOOM) buttons[i] = new JToggleButton();
      else buttons[i] = new JButton();

      buttons[i].setRolloverEnabled(true);
      buttons[i].setIcon((ImageIcon)ProyectoProperties.complexImages.get(buttonCads[i]));
      buttons[i].setRolloverIcon((ImageIcon)ProyectoProperties.complexImages.get(buttonCads[i] + "Over"));
      buttons[i].setRolloverSelectedIcon((ImageIcon)ProyectoProperties.complexImages.get(buttonCads[i] + "Pressed"));
      buttons[i].setPressedIcon((ImageIcon)ProyectoProperties.complexImages.get(buttonCads[i] + "Pressed"));
      buttons[i].setDisabledIcon((ImageIcon)ProyectoProperties.complexImages.get(buttonCads[i] + "Disabled"));
      buttons[i].setDisabledSelectedIcon((ImageIcon)ProyectoProperties.complexImages.get(buttonCads[i] + "Disabled"));
      buttons[i].setSelectedIcon((ImageIcon)ProyectoProperties.complexImages.get(buttonCads[i] + "Pressed"));
      buttons[i].setFocusPainted(false);
      buttons[i].setBorderPainted(false);
      buttons[i].setContentAreaFilled(false);
      buttons[i].setMargin(new Insets(0, 0, 0, 0));
      buttons[i].setBorder(BorderFactory.createEmptyBorder());
      buttons[i].addActionListener(this);
      buttons[i].setToolTipText((String)ProyectoProperties.complexImages.get(buttonCads[i] + "Label"));
      panelButton.add(buttons[i]);
    }

    panel.add(panelButton, BorderLayout.NORTH);
    panelButton.setBorder(BorderFactory.createEtchedBorder());

    JPanel dirPanel = new JPanel();
    dirPanel.setLayout(new BorderLayout());
    dirPanel.setBorder(BorderFactory.createEtchedBorder());
    dirPanel.add(new JLabel(" Dirección: "), BorderLayout.WEST);

    addressTxt = new JTextField();
    addressTxt.addActionListener(this);

    dirPanel.add(addressTxt, BorderLayout.CENTER);
    panel.add(dirPanel, BorderLayout.SOUTH);

    contentPane.add(panel, BorderLayout.NORTH);

    verticalScrollBar = new JScrollBar(JScrollBar.VERTICAL, 0, 0, 0, 180);
    horizontalScrollBar = new JScrollBar(JScrollBar.HORIZONTAL, 0, 0, 0, 180);

    verticalScrollBar.setVisible(false);
    horizontalScrollBar.setVisible(false);

    imagePanel = new ImagePanel(this);
    imagePanel.setPreferredSize(new Dimension(400, 400));
    centerPanel.add(imagePanel, BorderLayout.CENTER);

    centerPanel.add(verticalScrollBar, BorderLayout.EAST);
    centerPanel.add(horizontalScrollBar, BorderLayout.SOUTH);

    JPanel downPanel = new JPanel();
    downPanel.setLayout(new BorderLayout());
    downPanel.add(statusTxt = new JLabel(""), BorderLayout.WEST);
    downPanel.add(bytesTransmittedLabel = new JLabel(""), BorderLayout.EAST);

    contentPane.add(downPanel, BorderLayout.SOUTH);

    buttons[BUTTON_ZOOM].setEnabled(false);
    buttons[BUTTON_VIEW].setEnabled(false);
    buttons[BUTTON_REFRESH].setEnabled(false);
  }

  public JScrollBar getHorizontalScrollBar()
  {
    return horizontalScrollBar;
  }

  public JScrollBar getVerticalScrollBar()
  {
    return verticalScrollBar;
  }

  public void notifyImageInfo(String info)
  {
    statusTxt.setText(info);
  }

  public void notifyTotalBytes(int bytes)
  {
    if(bytes == 0) bytesTransmittedLabel.setText("");
    else bytesTransmittedLabel.setText("Bytes leidos: " + String.valueOf(bytes));
  }

  public void openImage(String imageName)
  {
    try {
      verticalScrollBar.setVisible(true);
      horizontalScrollBar.setVisible(true);

      buttons[BUTTON_ZOOM].setSelected(false);

      imagePanel.openImage(imageName);

      addressTxt.setText(imageName);

      Dimension imageSize = imagePanel.getImageRealSize();
      statusTxt.setText("Imagen: " + imageSize.width + "x" + imageSize.height + "  Escala: " + imagePanel.getScale() + "%");

      imagePanel.setPreferredSize(imagePanel.getImageSize());
      pack();

      buttons[BUTTON_ZOOM].setEnabled(true);
      buttons[BUTTON_VIEW].setEnabled(true);
      buttons[BUTTON_REFRESH].setEnabled(true);

    } catch(Exception ex) {

      if(ex.getMessage() != null)
        JOptionPane.showMessageDialog(this, "Error al cargar la imagen:\n" + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
      else {
        JOptionPane.showMessageDialog(this, "Error al cargar la imagen!!!", "Error", JOptionPane.ERROR_MESSAGE);
        ex.printStackTrace();
      }

      verticalScrollBar.setVisible(false);
      horizontalScrollBar.setVisible(false);

      bytesTransmittedLabel.setText("");
      addressTxt.setText("");
      statusTxt.setText("");

      buttons[BUTTON_ZOOM].setEnabled(false);
      buttons[BUTTON_VIEW].setEnabled(false);
      buttons[BUTTON_REFRESH].setEnabled(false);
    }
  }

  public void actionPerformed(ActionEvent e)
  {
    if(e.getSource() == buttons[BUTTON_OPEN]) {
      if(fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION)
        openImage(fileChooser.getSelectedFile().getPath());

    } else if(e.getSource() == buttons[BUTTON_ZOOM]) {
      imagePanel.setZoomMode(! imagePanel.getZoomMode());

    } else if(e.getSource() == buttons[BUTTON_VIEW]) {
      imagePanel.showViewFrame();

    } else if(e.getSource() == buttons[BUTTON_REFRESH]) {
      openImage(addressTxt.getText());

    } else if(e.getSource() == addressTxt) {
      openImage(addressTxt.getText());
    }
  }

  public void windowOpened(WindowEvent e) { }
  public void windowClosing(WindowEvent e) { }
  public void windowIconified(WindowEvent e) { }
  public void windowDeiconified(WindowEvent e) { }
  public void windowActivated(WindowEvent e) { }
  public void windowDeactivated(WindowEvent e) { }

  public void windowClosed(WindowEvent e)
  {
    System.exit(0);
  }

  public void componentResized(ComponentEvent e) {}
  public void componentHidden(ComponentEvent e) {}
  public void componentMoved(ComponentEvent e) {}
  public void componentShown(ComponentEvent e) {}
}