/*
 * jNPad v0.3 - jNPad's an Simple Text Editor written in Java
 *
 * Copyright (C) 2014-2017  rgs
 *
 * Require JDK 1.6 (or later)
 *
 * 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 2 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, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 *
 * Info, Questions, Suggestions & Bugs Report to rgsevero@gmail.com
 */

package jnpad.ui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import jnpad.GUIUtilities;
import jnpad.JNPadBundle;
import jnpad.ui.layout.VerticalFlowLayout;

/**
 * 
 * @version 0.3
 * @since   jNPad v0.1
 */
public class FontChooserDialog extends EscapableDialog {
  JPanel                      contentPane;
  JPanel                      pnLists          = new JPanel();
  JPanel                      pnPreview        = new JPanel();
  JPanel                      pnButtons        = new JPanel();
  JTextField                  tfFonts          = new JTextField();
  JTextField                  tfSizes          = new JTextField();
  JTextField                  tfStyles         = new JTextField();
  JButton                     btOk             = GUIUtilities.createOkButton();
  JButton                     btCancel         = GUIUtilities.createCancelButton();
  JLabel                      lbExample        = new JNPadLabel();
  JList                       lsFonts, lsSizes, lsStyles;

  private boolean             okPressed;
  private Font                _font;

  /** Logger */
  private final static Logger LOGGER           = Logger.getLogger(FontChooserDialog.class.getName());

  /** UID */
  private static final long   serialVersionUID = 2179003477367992324L;

  /**
   * Instantiates a new font chooser dialog.
   *
   * @param window the window
   * @param title the title
   * @param modal the modal
   * @param font the font
   * @throws HeadlessException the headless exception
   */
  public FontChooserDialog(Window window, String title, boolean modal, Font font) throws HeadlessException {
    super(window, title);
    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    _font = font;
    try {
      window.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
      jbInit();
      setModal(modal);
    }
    catch (Exception ex) {
      LOGGER.log(Level.WARNING, ex.getMessage(), ex);
    }
    finally {
      window.setCursor(Cursor.getDefaultCursor());
    }
  }

  /**
   * Component initialization.
   *
   * @throws Exception the exception
   */
  private void jbInit() throws Exception {
    contentPane = (JPanel) super.getContentPane();
    contentPane.setLayout(new BorderLayout());

    JPanel panel_1 = createTextFieldAndListPanel(JNPadBundle.getString("FontChooserDialog.font"), tfFonts, lsFonts = new JList(GUIUtilities.getAvailableFontFamilyNames())); //$NON-NLS-1$
    tfFonts.setColumns(15);
    tfFonts.setText(_font.getName());
    tfFonts.setEnabled(false);
    lsFonts.setCellRenderer(new FontNameCellRenderer());

    JPanel panel_2 = createTextFieldAndListPanel(JNPadBundle.getString("FontChooserDialog.size"), tfSizes, lsSizes = new JList(GUIUtilities.getStandardFontSizes())); //$NON-NLS-1$
    lsSizes.setSelectedValue(String.valueOf(_font.getSize()), true);
    tfSizes.setColumns(15);
    tfSizes.setText(String.valueOf(_font.getSize()));

    JPanel panel_3 = createTextFieldAndListPanel(JNPadBundle.getString("FontChooserDialog.style"), tfStyles, lsStyles = new JList(GUIUtilities.getFontStyles())); //$NON-NLS-1$
    lsStyles.setSelectedIndex(_font.getStyle());
    tfStyles.setColumns(15);
    tfStyles.setText( (String) lsStyles.getSelectedValue());
    tfStyles.setEnabled(false);
    lsStyles.setCellRenderer(new FontStylesCellRenderer());

    Font font = lsStyles.getFont();
    font = font.deriveFont(Font.PLAIN);
    lsFonts.setFont(font);
    lsSizes.setFont(font);
    lsStyles.setFont(font);

    ListSelectionHandler listSelectionHandler = new ListSelectionHandler();

    lsFonts.addListSelectionListener(listSelectionHandler);
    lsSizes.addListSelectionListener(listSelectionHandler);
    lsStyles.addListSelectionListener(listSelectionHandler);

    pnLists.setLayout(new GridLayout(0, 3, 6, 6));
    pnLists.add(panel_1);
    pnLists.add(panel_2);
    pnLists.add(panel_3);

    lbExample.setText("aAbBcCdDeE 12345 +-*\\ =<> :,. \"?' ()[]{}"); //$NON-NLS-1$

    pnPreview.setBorder(BorderFactory.createCompoundBorder(
      BorderFactory.createTitledBorder(JNPadBundle.getString("FontChooserDialog.preview")), //$NON-NLS-1$
      GUIUtilities.createEmptyBorder(2)));

    pnPreview.add(lbExample);

    btOk.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(final ActionEvent e) {
        okPressed = true;
        dispose();
      }
    });

    btCancel.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(final ActionEvent e) {
        dispose();
      }
    });

    pnButtons.setLayout(new FlowLayout(FlowLayout.RIGHT));
    pnButtons.add(btOk);
    pnButtons.add(btCancel);

    preview();

    pnLists.setBorder(GUIUtilities.createEmptyBorder(5, 0));

    contentPane.add(pnLists, BorderLayout.NORTH);
    contentPane.add(pnPreview, BorderLayout.CENTER);
    contentPane.add(pnButtons, BorderLayout.SOUTH);

    Dimension prefSize = lbExample.getPreferredSize();
    prefSize.height = 50;
    lbExample.setPreferredSize(prefSize);

    getRootPane().setDefaultButton(btOk);

    lsFonts.setSelectedValue(_font.getName(), true);
    setResizable(false);
  }

  /**
   * Escape pressed.
   */
  @Override
  protected void escapePressed() {
    dispose();
  }
  
  /**
   *
   */
  private void preview() {
    lbExample.setFont(buildFont());
  }

  /**
   *
   * @param label String
   * @param textField JTextField
   * @param list JList
   * @return JPanel
   */
  private JPanel createTextFieldAndListPanel(String label, JTextField textField, JList list) {
    JPanel p = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 5, true, false));
    p.add(new JNPadLabel(label));
    p.add(textField);
    JPanel panel = new JPanel(new BorderLayout(6, 6));
    panel.add(p, BorderLayout.NORTH);
    panel.add(new JScrollPane(list), BorderLayout.CENTER);
    return panel;

    /*GridBagLayout layout = new GridBagLayout();
    JPanel panel = new JPanel(layout);

    GridBagConstraints c = new GridBagConstraints();
    c.gridx = c.gridy = 0;
    c.gridwidth = c.gridheight = 1;
    c.fill = GridBagConstraints.BOTH;
    c.weightx = 1.0f;

    JLabel _label = new JNPadLabel(label);
    layout.setConstraints(_label, c);
    panel.add(_label);

    c.gridy = 1;
    Component vs = Box.createVerticalStrut(6);
    layout.setConstraints(vs, c);
    panel.add(vs);

    c.gridy = 2;
    layout.setConstraints(textField, c);
    panel.add(textField);

    c.gridy = 3;
    vs = Box.createVerticalStrut(6);
    layout.setConstraints(vs, c);
    panel.add(vs);

    c.gridy = 4;
    c.gridheight = GridBagConstraints.REMAINDER;
    JScrollPane scroller = new JScrollPane(list);
    layout.setConstraints(scroller, c);
    panel.add(scroller);

    return panel;*/
  }

  /**
   *
   * @return boolean
   */
  public boolean isOKPressed() {return okPressed;}

  /**
   *
   * @return Font
   */
  public Font getSelectedFont() {
    return (!okPressed) ? null : buildFont();
  }

  /**
   * Builds the font.
   *
   * @return Font
   */
  private Font buildFont() {
    int fontSize;
    try {
      fontSize = Integer.parseInt(tfSizes.getText());
    }
    catch (Exception e) {
      fontSize = 12;
    }

    return new Font(tfFonts.getText(), lsStyles.getSelectedIndex(), fontSize);
  }

  //////////////////////////////////////////////////////////////////////////////
  private class ListSelectionHandler implements ListSelectionListener {
    /**
     *
     * @param e ListSelectionEvent
     */
    public void valueChanged(ListSelectionEvent e) {
      Object obj = e.getSource();
      if (obj == lsFonts) {
        String family = (String) lsFonts.getSelectedValue();
        if (family != null)
          tfFonts.setText(family);
      }
      else if (obj == lsSizes) {
        String size = (String) lsSizes.getSelectedValue();
        if (size != null)
          tfSizes.setText(size);
      }
      else if (obj == lsStyles) {
        String style = (String) lsStyles.getSelectedValue();
        if (style != null)
          tfStyles.setText(style);
      }
      preview();
    }
  }
  //////////////////////////////////////////////////////////////////////////////

  //////////////////////////////////////////////////////////////////////////////
  private static class FontNameCellRenderer extends DefaultListCellRenderer {
    /** UID */
    private static final long serialVersionUID = 5496187409487166560L;

    /**
     *
     * @param list JList
     * @param value Object
     * @param index int
     * @param isSelected boolean
     * @param cellHasFocus boolean
     * @return Component
     */
    @Override
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
      JLabel comp = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
      if (value instanceof String) {
        String str = (String) value;
        Font font1 = list.getFont();
        Font font2 = new Font(str, font1.getStyle(), font1.getSize());
        if (font2.canDisplayUpTo(str) == -1) {
          comp.setFont(font2);
        }
      }
      return comp;
    }
  }
  //////////////////////////////////////////////////////////////////////////////

  //////////////////////////////////////////////////////////////////////////////
  private static class FontStylesCellRenderer extends DefaultListCellRenderer {
    /** UID */
    private static final long serialVersionUID = 4979127865961986980L;

    /**
     * Gets the list cell renderer component.
     *
     * @param list the list
     * @param value the value
     * @param index the index
     * @param isSelected is selected
     * @param cellHasFocus the cell has focus
     * @return the list cell renderer component
     * @see javax.swing.DefaultListCellRenderer#getListCellRendererComponent(javax.swing.JList, java.lang.Object, int, boolean, boolean)
     */
    @Override
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
      JLabel comp = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
      if (value instanceof String && (index >= 0 && index <= 3)) {
        String str = (String) value;
        Font font1 = list.getFont();
        Font font2 = new Font(font1.getName(), index, font1.getSize());
        if (font2.canDisplayUpTo(str) == -1) {
          comp.setFont(font2);
        }
      }
      return comp;
    }
  }
  //////////////////////////////////////////////////////////////////////////////

} // fin de FontChooserDialog
