/*
 * 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.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.event.ChangeEvent;

import jnpad.config.Config;
import jnpad.text.BufferSet;
import jnpad.text.Buffer;
import jnpad.text.Viewer;
import jnpad.util.Utilities;

/**
 * The Class JNPadViewer.
 *
 * @version 0.3
 * @since jNPad 0.1
 */
public abstract class JNPadViewer extends Viewer {
  JMenu                       mWindow;
  ButtonGroup                 bgWindow           = new ButtonGroup();
  boolean                     isItemStateEnabled = true;
  final ItemListener          itemHandler        = new ItemHandler();

  static ImageIcon            iiFile;
  static ImageIcon            iiFileReadOnly;
  static ImageIcon            iiFileModified;
  static ImageIcon            iiFileModifiedReadOnly;
  static ImageIcon            iiFileNew;
  static ImageIcon            iiFileNewReadOnly;

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

  /** UID */
  private static final long   serialVersionUID   = -812875419301736726L;

  static {
    try {
      iiFile                     = GUIUtilities.getIcon("file.png");                       //$NON-NLS-1$
      iiFileReadOnly             = GUIUtilities.getIcon("file-readonly.png");              //$NON-NLS-1$
      iiFileModified             = GUIUtilities.getIcon("file-modified.png");              //$NON-NLS-1$
      iiFileModifiedReadOnly     = GUIUtilities.getIcon("file-modified-readonly.png");     //$NON-NLS-1$
      iiFileNew                  = GUIUtilities.getIcon("file-new.png");                   //$NON-NLS-1$
      iiFileNewReadOnly          = GUIUtilities.getIcon("file-new-readonly.png");          //$NON-NLS-1$
    }
    catch(Exception ex) {
      LOGGER.log(Level.WARNING, ex.getMessage(), ex);
    }
  }
  
  /**
   * Instantiates a new jNPad viewer.
   *
   * @param jNPad the jNPad's frame
   * @param mWindow the window menu
   */
  public JNPadViewer(JNPadFrame jNPad, JMenu mWindow) {
    super(jNPad);
    this.mWindow = mWindow;
  }
  
  /**
   * Gets the jNPad's frame.
   *
   * @return the jNPad's frame
   */
  JNPadFrame getJNPad() {
    return _jNPad;
  }
  
  /**
   * Handle state changed.
   *
   * @param e ChangeEvent
   * @see jnpad.text.Viewer#handleStateChanged(javax.swing.event.ChangeEvent)
   */
  @Override
  protected void handleStateChanged(final ChangeEvent e) {
    if (isSuppressStateChangedEvents()) {
      return;
    }

    if (getActiveIndex() <= -1) { // no pasa
      _jNPad.setTitle(JNPad.TITLE);
      return;
    }

    Buffer buffer = getActiveBuffer();
    buffer.requestFocus();

    _jNPad.handleStateChanged(buffer);

    String path = buffer.getFilePath();
    
    for (Enumeration<?> en = bgWindow.getElements(); en.hasMoreElements();) {
      JRadioButtonMenuItem rbmi = (JRadioButtonMenuItem) en.nextElement();
      if (rbmi.getToolTipText().equals(path)) {
        if (!rbmi.isSelected()) {
          isItemStateEnabled = false;
          rbmi.setSelected(true);
          isItemStateEnabled = true;
        }
        break;
      }
    }
  }

  /**
   * Gets the icon.
   *
   * @param buffer the buffer
   * @return the icon
   */
  protected Icon getIcon(Buffer buffer) {
    Icon icon;

    if (buffer.isDirty() && !buffer.isReadOnly()) {
      icon = iiFileModified;
    }
    else if (buffer.isDirty() && buffer.isReadOnly()) {
      icon = iiFileModifiedReadOnly;
    }
    else if (!buffer.isDirty() && buffer.isReadOnly()) {
      icon = iiFileReadOnly;
    }
    else if (buffer.isNew() && !buffer.isReadOnly()) {
      icon = iiFileNew;
    }
    else if (buffer.isNew() && buffer.isReadOnly()) {
      icon = iiFileNewReadOnly;
    }
    else {
      icon = iiFile;
    }

    return icon;
  }

  /**
   * Gets the title.
   *
   * @param buffer the buffer
   * @return the title
   */
  protected String getTitle(Buffer buffer) {
    String path = buffer.getFilePath();
    String name = Utilities.getFileName(path);

    // mostrar la extensión en el nombre del archivo
    if (!Config.TAB_FILE_EXTENSION.getValue()) {
      int j = name.lastIndexOf('.');
      if (j > -1) {
        name = name.substring(0, j);
      }
    }

    return name;
  }

  /**
   * Sets the all component icon.
   */
  public void setAllComponentIcon() {
    for (int i = 0; i < getBufferCount(); i++) {
      setComponentIconAt(i);
    }
  }  
  
  /**
   * Refresh name and icon.
   */
  public void refreshNameAndIcon() {
    if (Config.TAB_FILE_ICON.getValue()) {
      for (int i = 0; i < getBufferCount(); i++) {
        setComponentIconAt(i);
      }
    }
    else {
      for (int i = 0; i < getBufferCount(); i++) {
        _bufferSet.setIconAt(i, null);
      }
    }
    if (Config.TAB_FILE_EXTENSION.getValue()) {
      for (int i = 0; i < getBufferCount(); i++) {
        setTitleAt(i, getTitle(getBufferAt(i)));
      }
    }
  }  

  /**
   * Sets the component icon at.
   *
   * @param index the new component icon at
   * @see jnpad.text.Viewer#setComponentIconAt(int)
   */
  @Override
  public void setComponentIconAt(int index) {
    Buffer buffer = getBufferAt(index);

    final Icon icon = getIcon(buffer);

    _bufferSet.setIconAt(index, icon);
    
    for (BufferSet bufferSet : getBufferSets()) {
      if (bufferSet == _bufferSet)
        continue;
      for (Buffer buff : bufferSet) {
        if (buffer.equals(buff)) {
          bufferSet.setIconAt(bufferSet.indexOfComponent(buff), icon);
        }
      }
    }
  }
  
  /**
   * Adds the.
   *
   * @param buffer the buffer
   * @return the buffer
   * @see jnpad.text.Viewer#add(jnpad.text.Buffer)
   */
  @Override
  public Buffer add(Buffer buffer) {
    String path = buffer.getFilePath();
    String name = Utilities.getFileName(path);

    final String title = getTitle(buffer);
    final Icon   icon  = Config.TAB_FILE_ICON.getValue() ? getIcon(buffer) : null;

      // agrega un item al menu Ventana
    JRadioButtonMenuItem rbmi = new JRadioButtonMenuItem(name);
    rbmi.setToolTipText(path);
    rbmi.addItemListener(itemHandler);
    mWindow.add(rbmi);
    bgWindow.add(rbmi);

    // agrega el component al panel
    _bufferSet.insertTab(title, icon, buffer, path, _bufferSet.getTabCount());
    for (BufferSet bufferSet : getBufferSets()) {
      if (bufferSet != _bufferSet) {
        bufferSet.insertTab(title, icon, create(bufferSet, buffer), path, bufferSet.getTabCount());
      }
    }

    if (getBufferCount() == 2) {
      _jNPad.actions.previousBufferAction.setEnabled(true);
      _jNPad.actions.nextBufferAction.setEnabled(true);
    }

    return buffer;
  }
  
  /**
   * Removes the view at.
   *
   * @param index the index
   * @see jnpad.text.Viewer#removeBufferAt(int)
   */
  @Override
  public void removeBufferAt(int index) {
    String path = getBufferAt(index).getFilePath();
    
    super.removeBufferAt(index);

    final int len = getBufferCount();

    if (len == 0) {
      _jNPad.reset();
    }
    else if (len == 1) {
      _jNPad.actions.previousBufferAction.setEnabled(false);
      _jNPad.actions.nextBufferAction.setEnabled(false);
    }

    for (Enumeration<?> en = bgWindow.getElements(); en.hasMoreElements();) {
      JRadioButtonMenuItem rbmi = (JRadioButtonMenuItem) en.nextElement();
      if (rbmi.getToolTipText().equals(path)) {
        mWindow.remove(rbmi);
        bgWindow.remove(rbmi);
        rbmi.removeItemListener(itemHandler);
        break;
      }
    }

    if (len > 0) {
      path = getToolTipTextAt(getActiveIndex());
      for (Enumeration<?> en = bgWindow.getElements(); en.hasMoreElements();) {
        JRadioButtonMenuItem rbmi = (JRadioButtonMenuItem) en.nextElement();
        if (rbmi.getToolTipText().equals(path)) {
          rbmi.setSelected(true);
          break;
        }
      }
    }
  }

  /**
   * Sets the tool tip text at.
   *
   * @param index the index
   * @param toolTipText the tool tip text
   * @see jnpad.text.Viewer#setToolTipTextAt(int, java.lang.String)
   */
  @Override
  public void setToolTipTextAt(int index, String toolTipText) {
    String oldToolTipText = getToolTipTextAt(index);

    // establecer el tooltip
    super.setToolTipTextAt(index, toolTipText);

    for (Enumeration<?> en = bgWindow.getElements(); en.hasMoreElements();) {
      JRadioButtonMenuItem rbmi = (JRadioButtonMenuItem) en.nextElement();
      if (rbmi.getToolTipText().equals(oldToolTipText)) {
        rbmi.setToolTipText(toolTipText);
        String text;
        if (Utilities.isURL(oldToolTipText)) {
          text = toolTipText.substring(toolTipText.lastIndexOf('/') + 1);
        }
        else {
          text = toolTipText.substring(toolTipText.lastIndexOf(Utilities.DIR_SEPARATOR) + 1);
        }
        rbmi.setText(text);
        break;
      }
    }
  }
  
  //////////////////////////////////////////////////////////////////////////////
  /**
   * The Class ItemHandler.
   */
  class ItemHandler implements ItemListener, Serializable {
    /** UID */
    private static final long serialVersionUID = 1820255320037614656L;

    /**
     * Item state changed.
     *
     * @param e ItemEvent
     * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
     */
    @Override
    public void itemStateChanged(final ItemEvent e) {
      if (!isItemStateEnabled) {
        return;
      }

      String tootip = ((JRadioButtonMenuItem) e.getItem()).getToolTipText();

      for (int i = 0; i < _bufferSet.getTabCount(); i++) {
        if (_bufferSet.getToolTipTextAt(i).equals(tootip)) {
          if (_bufferSet.getSelectedIndex() != i) {
            _bufferSet.setSelectedIndex(i);
          }
          break;
        }
      }
    }
  }
  //////////////////////////////////////////////////////////////////////////////

}
