/**
 *  Licensed under GPL. For more information, see
 *    http://jaxodraw.sourceforge.net/license.html
 *  or the LICENSE file in the jaxodraw distribution.
 */
package net.sf.jaxodraw.gui.menu;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
//import java.awt.event.KeyEvent;

import java.beans.PropertyChangeEvent;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.swing.JMenuItem;

import net.sf.jaxodraw.io.JaxoIO;
import net.sf.jaxodraw.util.JaxoConstants;
import net.sf.jaxodraw.util.JaxoLanguage;
import net.sf.jaxodraw.util.JaxoPrefs;

/**
 * A JaxoMenu for opening recent files.
 */
public class OpenRecentMenu extends JaxoMenu {
    private static final long serialVersionUID = 7526471155622776147L;

    // Maximum size of recent files stored at runtime
    // (only the first four are put into menu/preferences, the others
    // are not used at the moment - one could hide the menu items of
    // open files)
    // The number of files stored is determined by JaxoPrefs.MAX_RECENT_FILES

    private static final int MAX_SIZE = 100;

    // recent files
    private final List<JMenuItem> recentFiles = new ArrayList<JMenuItem>(MAX_SIZE);

    /** Creates a new instance of NewMenu. */
    public OpenRecentMenu() {
        super();
        readRecentFiles();
        addSeparator();
        this.add(clearRFMenuItem());
        //When no recent file is present disable the Clear menu entry
        if (this.getItemCount() == 2) {
            this.getItem(1).setEnabled(false);
        }
        JaxoMenuUtils.setLanguageKey(this, "OpenRecentMenu.title");
    }

    /**
     * Applies a property change event.
     *
     * @param e the change event.
     */
    public void propertyChange(final PropertyChangeEvent e) {
        final String name = e.getPropertyName();
        if ("Jaxo.recentFile".equals(name)) {
            if (e.getNewValue() == null) {
                removeRecentFile((String) e.getOldValue());
            } else if (e.getOldValue() == null) {
                addRecentFile((String) e.getNewValue());
            }
        }
    }

     /** Adds a new entry to this menu, with a shortcut to
     * a recently opened graph.
     * @param saveFileName The full path to the saved graph.
     */
    public final void addRecentFile(final String saveFileName) {
        if (saveFileName.length() > 0) {
            doAddRecentFile(saveFileName);
            pushRecentFiles();
        }
    }

    /** Removes the given file name from the list of recent files.
     * @param saveFileName The file to remove.
     */
    public final void removeRecentFile(final String saveFileName) {
        for (final Iterator<JMenuItem> i = recentFiles.iterator(); i.hasNext();) {
            final JMenuItem m = i.next();

            if (m.getName().equals(saveFileName)) {
                i.remove();
                pushRecentFiles();
                return;
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    public final void updateLanguage() {
        super.updateLanguage();

        pushRecentFiles();
    }

      //
     // private methods
    //

   private void readRecentFiles() {
        final String[] rf =  JaxoPrefs.getRecentFiles();

        for (int i = rf.length - 1; i >= 0; --i) {
            final String fileName = rf[i];

            if (fileName.length() > 0) {
                doAddRecentFile(fileName);
            }
        }

        pushRecentFiles();
    }

    private JMenuItem newRecentFileMenuItem(final String fileName) {
        final JMenuItem result = new JMenuItem();
        result.setName(fileName);
        result.setToolTipText(fileName);
        result.putClientProperty("Jaxo.text", JaxoIO.shortName(fileName));
        JaxoMenuUtils.setActionCommand(result, JaxoConstants.RECENT_FILE);

        // add all the ActionListeners that have been added to other MIs
        final ActionListener[] l = this.getActionListeners();
        for (int i = 0; i < l.length; i++) {
            result.addActionListener(l[i]);
        }

        return result;
    }

    // add without writing to preferences
    private void doAddRecentFile(final String saveFileName) {
        for (final Iterator<JMenuItem> i = recentFiles.iterator(); i.hasNext();) {
            final JMenuItem m = i.next();

            if (m.getName().equals(saveFileName)) {
                i.remove();
                break;
            }
        }

        recentFiles.add(0, newRecentFileMenuItem(saveFileName));

        if (recentFiles.size() > MAX_SIZE) {
            recentFiles.subList(MAX_SIZE, recentFiles.size()).clear();
        }
    }

    // Put current recent files into menu bar and preferences
    private void pushRecentFiles() {
        //int index = 1 + getPopupMenu().getComponentIndex(beforeRecentFiles);
        int index = 0;

        while (getMenuComponent(index) instanceof JMenuItem) {
            remove(index);
        }

        JaxoPrefs.clearRecentFiles();

        //int index = 0;
        int number = 0;

        for (final Iterator<JMenuItem> i = recentFiles.iterator();
                i.hasNext() && (number < JaxoPrefs.MAX_RECENT_FILES); number++) {
            final JMenuItem m = i.next();

            m.setText(JaxoLanguage.message(
                    "OpenRecentMenu.fileNo%0Named%1",
                    Integer.valueOf(number + 1), m.getClientProperty("Jaxo.text")));
            //JaxoMenuUtils.setAccelerator(m, keyList[number], 0);

            insert(m, index);

            JaxoPrefs.addRecentFile(m.getName());

            index++;
        }

        //beforeRecentFiles.setVisible(number != 0);


        // If there are only 3 items the menu has ben cleared; in this case
        // enable the clear entry again
        if (this.getItemCount() == 3) {
            this.getItem(2).setEnabled(true);
        }
    }

    private JMenuItem clearRFMenuItem() {
        final JMenuItem clearRFMI = new JMenuItem();
        clearRFMI.setActionCommand("ClearRFMenu");
        JaxoMenuUtils.setLanguageKey(clearRFMI, "OpenRecentMenu.clear");
        clearRFMI.addActionListener(
                new ActionListener() {
                        public void actionPerformed(final ActionEvent e) {
                            if (e.getActionCommand().equals("ClearRFMenu")) {
                                clearRFMenu();
                            }
                        }
                }
        );
        return clearRFMI;
    }

    /* Clear the recent file menu, removing files also form the preferences */

    private void clearRFMenu() {
        recentFiles.clear();
        revalidateMenu();
        //Remove files from the preferences
        pushRecentFiles();
    }

    private void revalidateMenu() {
        final int entries = this.getItemCount();
        for (int i = entries - 3; i >= 0; --i) {
            this.remove(i);
        }
        this.getItem(1).setEnabled(false);
    }

}
