/*
 * 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;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import jnpad.config.Config;
import jnpad.text.IBuffer;
import jnpad.ui.EscapableDialog;
import jnpad.ui.JNPadCheckBox;
import jnpad.ui.JNPadLabel;
import jnpad.ui.icon.CompositeIcon;
import jnpad.ui.tab.ITabbedPane;
import jnpad.util.Utilities;

/**
 * The Class ExitDialog.
 *
 * @version 0.3
 * @since   jNPad v0.1
 */
public class ExitDialog extends EscapableDialog {
  JPanel                      contentPane;
  JPanel                      pnBackground               = new JPanel();
  JScrollPane                 scrollPane                 = new JScrollPane();
  JPanel                      pnList                     = new JPanel();
  JPanel                      pnFiles                    = new JPanel();
  JPanel                      pnClosingFilesNotSaved     = new JPanel();
  JPanel                      pnButtons                  = new JPanel();
  JPanel                      pnWest                     = new JPanel();
  JPanel                      pnEast                     = new JPanel();
  JButton                     btAll                      = new JButton();
  JButton                     btNone                     = new JButton();
  JButton                     btOk                       = new JButton();
  JButton                     btCancel                   = new JButton();
  GridLayout                  gridLayout                 = new GridLayout();
  GridLayout                  gridLayout2                = new GridLayout();

  private JNPadFrame          jNPad;
  private ITabbedPane         tabbedPane;
  private boolean             isOk;
  private int                 mode;

  private List<JCheckBox>     l_checkBoxs                = new ArrayList<JCheckBox>();

  private List<JCheckBox>     l_checkBoxs2               = new ArrayList<JCheckBox>();

  /** */
  public static final int     SAVE                       = 1;

  /** */
  public static final int     CLOSE                      = 2;

  /** */
  public static final int     CLOSE_WITHOUT_CONFIRMATION = 3;

  private static final Color
      BACKGROUND           = Config.TEXT_BACKGROUND.getValue(),
      FOREGROUND           = Config.TEXT_FOREGROUND.getValue(),
      SELECTION_BACKGROUND = Config.TEXT_SELECTION_BACKGROUND.getValue(),
      SELECTION_FOREGROUND = Config.TEXT_SELECTION_FOREGROUND.getValue();

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

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

  /**
   * Instantiates a new exit dialog.
   *
   * @param jNPad the jNPad frame
   * @param tabbedPane the tabbed pane
   * @param mode the mode
   * @throws HeadlessException the headless exception
   */
  private ExitDialog(JNPadFrame jNPad, ITabbedPane tabbedPane, int mode) throws HeadlessException {
    super(jNPad, Utilities.EMPTY_STRING, true);
    jNPad.repaint();
    this.jNPad = jNPad;
    this.tabbedPane = tabbedPane;
    this.mode = mode;
    try {
      jbInit();
    }
    catch (Exception ex) {
      LOGGER.log(Level.WARNING, ex.getMessage(), ex);
    }
  }

  /**
   * Component initialization.
   *
   * @throws Exception the exception
   */
  private void jbInit() throws Exception {
    contentPane = (JPanel) this.getContentPane();
    contentPane.setLayout(new BorderLayout());
    contentPane.add(pnButtons, BorderLayout.SOUTH);
    contentPane.add(pnBackground, BorderLayout.CENTER);
    pnBackground.setBorder(GUIUtilities.createEmptyBorder(5));
    pnBackground.setLayout(new BorderLayout());
    pnBackground.add(scrollPane, BorderLayout.CENTER);
    pnButtons.setLayout(new BorderLayout());
    pnButtons.add(pnWest, BorderLayout.WEST);
    pnButtons.add(pnEast, BorderLayout.EAST);
    pnEast.add(btOk, null);
    pnEast.add(btCancel, null);
    pnWest.add(btAll, null);
    pnWest.add(btNone, null);
    pnList.setBackground(BACKGROUND);
    pnList.setLayout(new BorderLayout());
    scrollPane.getViewport().add(pnList, null);
    pnList.add(pnFiles, BorderLayout.NORTH);
    pnFiles.setLayout(gridLayout);
    pnClosingFilesNotSaved.setLayout(gridLayout2);

    GUIUtilities.setLocalizedText(btAll, JNPadBundle.getAllButtonText());
    GUIUtilities.setLocalizedText(btNone, JNPadBundle.getNoneButtonText());
    GUIUtilities.setLocalizedText(btCancel, JNPadBundle.getCancelButtonText());
    GUIUtilities.setLocalizedText(btOk, JNPadBundle.getOkButtonText());

    Dimension dimension = btCancel.getPreferredSize();
    btAll.setPreferredSize(dimension);
    btNone.setPreferredSize(dimension);
    btOk.setPreferredSize(dimension);

    ActionListener actionHandler = new ActionHandler();

    btAll.addActionListener(actionHandler);
    btNone.addActionListener(actionHandler);
    btOk.addActionListener(actionHandler);
    btCancel.addActionListener(actionHandler);
  }

  /**
   * Load.
   *
   * @param text the text
   * @param tooltip the tooltip
   * @param icon the icon
   * @param isSelected is selected
   * @param list the list
   * @param panel the panel
   */
  private void load(String text, String tooltip, Icon icon, boolean isSelected, List<JCheckBox> list, JPanel panel) {
    Element elem = new Element(text, tooltip, icon, isSelected);
    panel.add(elem, null);
    list.add(elem.jCheckBox);
  }

  /**
   * Show dialog.
   *
   * @param jNPad the jNPad frame
   * @param tabbedPane the tabbed pane
   * @param mode the mode
   * @return true, if successful
   */
  public static boolean showDialog(JNPadFrame jNPad, ITabbedPane tabbedPane, int mode) {
    ExitDialog dlg = new ExitDialog(jNPad, tabbedPane, mode);

    boolean isOk = dlg.showFileSaveDialog();
    dlg.dispose();
    dlg = null;

    return isOk;
  }

  /**
   * Show file save dialog.
   *
   * @return true, if successful
   */
  private boolean showFileSaveDialog() {
    setTitle(mode == SAVE ? JNPadBundle.getString("ExitDialog.save") : JNPadBundle.getString("ExitDialog.close")); //$NON-NLS-1$ //$NON-NLS-2$
    int i = 0;
    for (int j = 0; j < tabbedPane.getTabCount(); j++) {
      IBuffer editFile = (IBuffer) tabbedPane.getComponentAt(j);
      boolean flag = false;
      if (editFile.isDirty() && mode == SAVE) {
        flag = true;
      }
      if (editFile.isDirty() || mode != SAVE) {
        load(get_name(editFile.getFilePath()), editFile.getFilePath(),
             get_icon(j), flag, l_checkBoxs, pnFiles);
        i++;
      }
    }

    if (i == 0) {
      return true;
    }

    gridLayout.setColumns(1);
    gridLayout.setRows(i);

    setSize(new Dimension(380, 300));
    validate();
    setLocationRelativeTo(jNPad);
    setVisible(true);

    return isOk;
  }

  /**
   * Gets the icon.
   *
   * @param index the index
   * @return the icon
   */
  private Icon get_icon(int index) {
    Icon icon;
    if ((index > -1) && (tabbedPane.getTabCount() > index)) {
      icon = tabbedPane.getIconAt(index);
      if (icon instanceof CompositeIcon && ((CompositeIcon) icon).hasMainIcon()) {
        icon = ((CompositeIcon) icon).getMainIcon();
      }
    }
    else {
      icon = null;
    }
    return icon;
  }

  /**
   * Gets the name.
   *
   * @param path the path
   * @return the name
   */
  private String get_name(String path) {
    String name;
    if (Utilities.isURL(path)) {
      name = path.substring(path.lastIndexOf('/') + 1);
    }
    else {
      name = path.substring(path.lastIndexOf(Utilities.DIR_SEPARATOR) + 1);
    }
    return name;
  }

  /**
   * Select all.
   *
   * @param flag the flag
   */
  private void selectAll(boolean flag) {
    if (mode == CLOSE_WITHOUT_CONFIRMATION) {
      for (JCheckBox aL_checkBoxs2 : l_checkBoxs2) {
        aL_checkBoxs2.getModel().setSelected(flag);
      }
    }
    else {
      for (JCheckBox l_checkBox : l_checkBoxs) {
        l_checkBox.getModel().setSelected(flag);
      }
    }
  }

  /**
   * File ok action.
   */
  private void fileOkAction() {
    for (JCheckBox cb : l_checkBoxs) {
      if (!cb.isSelected()) {
        continue;
      }
      if (mode == SAVE) {
        jNPad.saveFile(cb.getToolTipText());
      }
      else {
        jNPad.closeFile(cb.getToolTipText(), false);
      }
    }
  }

  /**
   * Ok.
   */
  private void ok() {
    if (mode == SAVE) {
      fileOkAction();
      isOk = true;
      setVisible(false);
    }
    else if (mode == CLOSE) {
      int j = 0;
      for (int k = 0; k < l_checkBoxs.size(); k++) {
        IBuffer editFile = (IBuffer) tabbedPane.getComponentAt(k);
        JCheckBox cb = l_checkBoxs.get(k);
        if (cb.isSelected() && editFile.isDirty()) {
          load(get_name(editFile.getFilePath()), editFile.getFilePath(),
               get_icon(k), true, l_checkBoxs2, pnClosingFilesNotSaved);
          j++;
        }
      }

      if (j == 0) {
        fileOkAction();
        isOk = true;
        setVisible(false);
      }
      setTitle(JNPadBundle.getString("ExitDialog.save")); //$NON-NLS-1$

      pnList.remove(pnFiles);
      pnList.add(pnClosingFilesNotSaved, BorderLayout.NORTH);
      gridLayout2.setColumns(1);
      gridLayout2.setRows(j);
      validate();
      repaint();

      setLocationRelativeTo(jNPad);
      mode = CLOSE_WITHOUT_CONFIRMATION;
    }
    else if (mode == CLOSE_WITHOUT_CONFIRMATION) {
      for (JCheckBox cb : l_checkBoxs2) {
        if (cb.isSelected()) {
          jNPad.saveFile(cb.getToolTipText());
        }
      }
      fileOkAction();
      isOk = true;
      setVisible(false);
    }
  }

  //////////////////////////////////////////////////////////////////////////////
  /**
   * The Class ActionHandler.
   */
  private class ActionHandler implements ActionListener {
    /**
     * Action performed.
     *
     * @param e the action event
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    @Override
    public void actionPerformed(ActionEvent e) {
      Object obj = e.getSource();
      if (obj == btAll)         selectAll(true);
      else if (obj == btNone)   selectAll(false);
      else if (obj == btOk)     ok();
      else if (obj == btCancel) setVisible(false);
    }
  }
  //////////////////////////////////////////////////////////////////////////////

  //////////////////////////////////////////////////////////////////////////////
  /**
   * The Class Element.
   */
  static class Element extends JPanel {
    JLabel                    jLabel                    = new JNPadLabel();
    JCheckBox                 jCheckBox                 = new JNPadCheckBox();

    private boolean           isItemStateChangedEnabled = true;

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

    /**
     * Instantiates a new element.
     *
     * @param text the text
     * @param tooltip the tooltip
     * @param icon the icon
     * @param isSelected is selected
     */
    Element(String text, String tooltip, Icon icon, boolean isSelected) {
      super(new FlowLayout(FlowLayout.LEFT, 2, 0));

      setBackground(BACKGROUND);
      
      add(jCheckBox, null);
      add(jLabel, null);

      jLabel.setText(text);
      jLabel.setOpaque(true);
      jLabel.setIcon(icon);
      jLabel.setToolTipText(tooltip);
      
      jCheckBox.setOpaque(true);
      jCheckBox.setBackground(BACKGROUND);
      jCheckBox.setToolTipText(tooltip);
      
      select(isSelected);

      jLabel.addMouseListener(new MouseHandler());
      jCheckBox.addItemListener(new ItemHandler());
    }

    /**
     * Select.
     *
     * @param isSelected is selected
     */
    private void select(boolean isSelected) {
      if (isSelected) {
        jLabel.setBackground(SELECTION_BACKGROUND);
        jLabel.setForeground(SELECTION_FOREGROUND);
      }
      else {
        jLabel.setBackground(BACKGROUND);
        jLabel.setForeground(FOREGROUND);
      }
      isItemStateChangedEnabled = false;
      jCheckBox.setSelected(isSelected);
      isItemStateChangedEnabled = true;
    }

    //////////////////////////////////////////////////////////////////////////////
    /**
     * The Class MouseHandler.
     */
    private class MouseHandler extends MouseAdapter {
      
      /**
       * Mouse pressed.
       *
       * @param e the mouse event
       * @see java.awt.event.MouseAdapter#mousePressed(java.awt.event.MouseEvent)
       */
      @Override
      public void mousePressed(MouseEvent e) {
        select(!jCheckBox.isSelected());
      }
    }
    //////////////////////////////////////////////////////////////////////////////

    //////////////////////////////////////////////////////////////////////////////
    /**
     * The Class ItemHandler.
     */
    private class ItemHandler implements ItemListener {
      /**
       * Item state changed.
       *
       * @param e the item event
       * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
       */
      @Override
      public void itemStateChanged(ItemEvent e) {
        if (!isItemStateChangedEnabled) {
          return;
        }
        select(jCheckBox.isSelected());
      }
    }
    //////////////////////////////////////////////////////////////////////////////
  }
  //////////////////////////////////////////////////////////////////////////////

}
