/*******************************************************************************
 * Copyright (c) 2013 Bill Tyros.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 * 
 * Contributors:
 *     Bill Tyros - initial API and implementation
 ******************************************************************************/
package tracer.gui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.Timer;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import tracer.rendering.Renderer;

@SuppressWarnings("serial")
public class RayTracerUI extends JFrame {
  // TODO: add "Show Render Info" button that pops up a message dialog with ->
  // size, number of samples, ...

  private static int renderCount = 0;
  private static final int TIME_BEFORE_SWITCH_TO_NEW_RENDER_TAB_IN_MS = 20;
  private final List<RenderPanel> renderPanels = new ArrayList<>();

  private final JTabbedPane tabbedPane;

  public RayTracerUI() {
    super(Messages.getString("RayTracerUI.window_title")); //$NON-NLS-1$
    tabbedPane = new JTabbedPane();

    tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);

    tabbedPane.addChangeListener(new ChangeListener() {
      @Override
      public void stateChanged(final ChangeEvent e1) {
        final Component p =
            ((JTabbedPane) e1.getSource()).getSelectedComponent();
        if (p != null) {
          RayTracerUI.this.pack();
          for (final RenderPanel panel : renderPanels) {
            panel.setVisible(false);
          }
          getSelectedRenderPanel().setVisible(true);
          RayTracerUI.this.setLocationByPlatform(false);
        }
      }
    });

    addWindowListener(new WindowAdapter() {
      @Override
      public final void windowClosing(final WindowEvent event) {
        Renderer.getInstance().stopRendering();
      }
    });
    setLayout(new BorderLayout());

    setJMenuBar(new RayTracerMenuBar(this));
    setContentPane(tabbedPane);
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    setResizable(false);
    pack();
    setLocationByPlatform(true);
    setVisible(true);

    final Graphics2D g2 = (Graphics2D) getGraphics();
    if (g2 != null) {
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
          RenderingHints.VALUE_ANTIALIAS_OFF);
      g2.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
          RenderingHints.VALUE_COLOR_RENDER_SPEED);
      g2.setRenderingHint(RenderingHints.KEY_DITHERING,
          RenderingHints.VALUE_DITHER_DISABLE);
    }
  }

  public RenderPanel createNewRenderPanel() {
    renderCount++;
    final RenderPanel newRenderPanel = new RenderPanel(this);
    this.renderPanels.add(newRenderPanel);
    final String title = Messages.getString("RayTracerUI.0") + renderCount;
    tabbedPane.addTab(title, newRenderPanel);
    final int index = renderPanels.size() - 1;
    final JPanel pnlTab = new JPanel();
    final JLabel lblTitle = new JLabel(title);
    final JButton btnClose = new JButton("x");
    pnlTab.add(lblTitle);
    pnlTab.add(btnClose);

    pnlTab.setOpaque(false);

    tabbedPane.setTabComponentAt(index, pnlTab);

    btnClose.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(final ActionEvent arg0) {
        final int index = tabbedPane.indexOfTab(title);
        if (index >= 0) {
          tabbedPane.removeTabAt(index);
          renderPanels.remove(index);
        }
      }
    });
    final Timer timer =
        new Timer(TIME_BEFORE_SWITCH_TO_NEW_RENDER_TAB_IN_MS,
            new ActionListener() {
              @Override
              public void actionPerformed(final ActionEvent e) {
                tabbedPane.setSelectedIndex(renderPanels.size() - 1);
              }
            });
    timer.setRepeats(false);
    timer.start();
    return newRenderPanel;
  }

  public RenderPanel getSelectedRenderPanel() {
    final int index = tabbedPane.getSelectedIndex();
    try {
      return renderPanels.get(index);
    } catch (final IndexOutOfBoundsException e) {
      return null;
    }
  }
}
