/**************************************************************************
 OmegaT - Computer Assisted Translation (CAT) tool 
          with fuzzy matching, translation memory, keyword search, 
          glossaries, and translation leveraging into updated projects.

 Copyright (C) 2012-2020 Thomas Cordonnier
               Home page: http://www.omegat.org/
               Support center: http://groups.yahoo.com/group/OmegaT/

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

package org.omegat.gui.dialogs;

import java.awt.Frame;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import java.io.*;
import java.nio.file.*;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.KeyStroke;

import org.omegat.gui.search.SearchModeBox;
import org.omegat.gui.glossary.GlossarySortCriteria;
import org.omegat.tokenizer.ITokenizer;
import org.omegat.util.OStrings;
import org.omegat.util.Preferences;

/**
 * 
 * @author Thomas Cordonnier
 */
@SuppressWarnings("serial")
public class GlossaryConfigDialog extends JDialog {
    /** A return status code - returned if Cancel button has been pressed */
    public static final int RET_CANCEL = 0;
    /** A return status code - returned if OK button has been pressed */
    public static final int RET_OK = 1;

	public static class ScriptItem {
		String name;
		Object item;
		
		public ScriptItem(String name, Object item) { this.name = name; this.item = item; }
		
		public String toString() { return name; }
		
		public String toOption() {
			if (item instanceof File) return "file:" + name;
			return item.toString();
		}
		
		public static ScriptItem find (javax.swing.JComboBox items, String findName) {
			for (int i = 0; i < items.getItemCount(); i++) {
				ScriptItem item0 = (ScriptItem) items.getItemAt(i);
				if (item0.name.equals(findName)) return item0;
				if (findName.startsWith("file:") && item0.name.equals(findName.substring(5))) return item0;
			}
			return (ScriptItem) items.getItemAt(0);
		}
	}
	
    /** Creates new form WorkflowOptionsDialog */
    public GlossaryConfigDialog(Frame parent) {
        super(parent, true);

        // HP
        // Handle escape key to close the window
        KeyStroke escape = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
        Action escapeAction = new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                dispose();
            }
        };
        getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(escape, "ESCAPE");
        getRootPane().getActionMap().put("ESCAPE", escapeAction);
        // END HP

        initComponents();

        getRootPane().setDefaultButton(okButton);

        // initializing options
        activeSrc.setSelected(Preferences.isPreference(Preferences.TRANSTIPS_SRC));
        activeTra.setSelected(Preferences.isPreference(Preferences.TRANSTIPS_TRA));
        suggest.setSelected(Preferences.isPreference(Preferences.TRANSTIPS_SUGGEST));
        ignoreTags.setSelected(Preferences.isPreference(Preferences.GLOSSARY_REMOVE_TAGS));
		removeSubwords.setSelected(Preferences.isPreference(Preferences.GLOSSARY_REMOVE_SUBWORDS));
		cbDoMerge.setSelected(Preferences.isPreferenceDefault(Preferences.GLOSSARY_PANE_DO_MERGE,true));
        templateList.setSelectedItem(ScriptItem.find(templateList, Preferences.getPreference(Preferences.GLOSSARY_PANE_TEMPLATE)));
        modeBox.loadPreferences (Preferences.TRANSTIPS + '_');
        StringBuffer configBuf = new StringBuffer(Preferences.getPreferenceDefault(Preferences.GLOSSARY_PANE_SORT_ORDER, "ACPL;ACPL"));
        fillModel((javax.swing.DefaultListModel<GlossarySortCriteria.WithDirection>) srcOrderList.getModel(), configBuf);
        fillModel((javax.swing.DefaultListModel<GlossarySortCriteria.WithDirection>) traOrderList.getModel(), configBuf);
        
        invalidate();
        pack(); setResizable(false);
    }
    
    private static void fillModel(javax.swing.DefaultListModel<GlossarySortCriteria.WithDirection> model, StringBuffer buf) {
        java.util.EnumSet<GlossarySortCriteria> set = java.util.EnumSet.noneOf(GlossarySortCriteria.class);
        while (! (buf.length() == 0 || buf.charAt(0) == ';')) {
            GlossarySortCriteria crit = GlossarySortCriteria.forChar(buf.charAt(0));
            model.addElement(new GlossarySortCriteria.WithDirection(crit, Character.isLowerCase(buf.charAt(0)))); set.add(crit); 
            buf.delete(0,1); 
        }
        if (buf.toString().startsWith(";")) buf.delete(0, 1);
        // Add missing values at the end
        java.util.EnumSet.allOf(GlossarySortCriteria.class).forEach(c0 -> { if (! set.contains(c0)) model.addElement(new GlossarySortCriteria.WithDirection(c0, false)); });
    }

    /** @return the return status of this dialog - one of RET_OK or RET_CANCEL */
    public int getReturnStatus() {
        return returnStatus;
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed"
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        okButton = new javax.swing.JButton();
        cancelButton = new javax.swing.JButton();
        activeSrc = new javax.swing.JCheckBox();
        org.openide.awt.Mnemonics.setLocalizedText(activeSrc, OStrings.getString("TF_OPTIONSMENU_GLOSSARY_UNDERLINE_SRC"));
        activeTra = new javax.swing.JCheckBox();
        org.openide.awt.Mnemonics.setLocalizedText(activeTra, OStrings.getString("TF_OPTIONSMENU_GLOSSARY_UNDERLINE_TRA"));
        suggest = new javax.swing.JCheckBox();
        org.openide.awt.Mnemonics.setLocalizedText(suggest, OStrings.getString("TF_OPTIONSMENU_GLOSSARY_SUGGEST"));
        ignoreTags= new javax.swing.JCheckBox();
		removeSubwords= new javax.swing.JCheckBox();
        org.openide.awt.Mnemonics.setLocalizedText(ignoreTags, OStrings.getString("TF_OPTIONSMENU_GLOSSARY_IGNORE_TAGS"));
        org.openide.awt.Mnemonics.setLocalizedText(removeSubwords, OStrings.getString("TF_OPTIONSMENU_GLOSSARY_REMOVE_SUBWORDS"));
        org.openide.awt.Mnemonics.setLocalizedText(suggest, OStrings.getString("TF_OPTIONSMENU_GLOSSARY_SUGGEST"));
        modeBox = new SearchModeBox (javax.swing.BoxLayout.Y_AXIS, ITokenizer.StemmingMode.GLOSSARY, null); // with keywords, not regex

        setTitle(OStrings.getString("GUI_MATCHWINDOW_SUBWINDOWTITLE_Glossary")); 
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                closeDialog(evt);
            }
        });
        getContentPane().setLayout(new BorderLayout());

        Box buttonsBox = Box.createHorizontalBox();
        this.add (buttonsBox, BorderLayout.SOUTH);
        Box bCheck = Box.createVerticalBox();
        this.add (bCheck, BorderLayout.NORTH);
        Box bCheckTips = Box.createHorizontalBox(); bCheck.add (bCheckTips);
        bCheckTips.add(activeSrc); bCheckTips.add(activeTra);
        Box bCheckOther = Box.createHorizontalBox(); bCheck.add (bCheckOther);
        bCheckOther.add (suggest); bCheckOther.add (ignoreTags);bCheckOther.add (removeSubwords); 
        Box boxTemplate = Box.createHorizontalBox(); bCheck.add (boxTemplate);
		boxTemplate.add (new javax.swing.JLabel(OStrings.getString("TF_OPTIONSMENU_GLOSSARY_TEMPLATE")));
        boxTemplate.add (templateList = new javax.swing.JComboBox());
		templateList.addItem (new ScriptItem(OStrings.getString("TF_OPTIONSMENU_GLOSSARY_TEMPLATE_HARDCODED_DEFAULT"), org.omegat.gui.glossary.GlossaryTextArea.DEFAULT_TEMPLATE));
		File scriptsDir = new File(Preferences.getPreferenceDefault(Preferences.SCRIPTS_DIRECTORY, org.omegat.util.StaticUtils.installDir() + "/scripts") + "/layout/glossary");	
		if (scriptsDir.exists()) 
			try {
				try (DirectoryStream<Path> stream = Files.newDirectoryStream(scriptsDir.toPath())) {
					for (Path p: stream) {
						File f = p.toFile();
						if (f.getName().endsWith(".groovy"))
							templateList.addItem (new ScriptItem(f.getName(), f));
					}
				}
			} catch (IOException io) {
				io.printStackTrace();
			}
		boxTemplate.add(cbDoMerge = new javax.swing.JCheckBox("Merge results", true));
		
		Box bSortOrder = Box.createHorizontalBox(); bCheck.add(bSortOrder);
		bSortOrder.add (new JLabel(OStrings.getString("TF_OPTIONSMENU_GLOSSARY_SORT")));
		final javax.swing.DefaultListModel<GlossarySortCriteria.WithDirection> srcModel = new javax.swing.DefaultListModel();
		bSortOrder.add (srcOrderList = new javax.swing.JList(srcModel));
		Box bSortButtonsSrc = Box.createVerticalBox(); bSortOrder.add(bSortButtonsSrc);
		javax.swing.JButton btnSrcUp, btnSrcDown, btnSrcReverse;
		bSortButtonsSrc.add(btnSrcUp = new javax.swing.JButton("^ UP")); bSortButtonsSrc.add(btnSrcDown = new javax.swing.JButton("v DOWN")); bSortButtonsSrc.add(btnSrcReverse = new javax.swing.JButton("v DESC"));
		btnSrcUp.addActionListener(ev -> { 
			if (srcOrderList.getSelectedIndex() > 0) {
				int idx = srcOrderList.getSelectedIndex();
				GlossarySortCriteria.WithDirection el = srcModel.getElementAt(idx);
				srcModel.remove(idx); srcModel.add(idx - 1, el);
			}
		});
		btnSrcDown.addActionListener(ev -> { 
			if ((srcOrderList.getSelectedIndex() >= 0) && (srcOrderList.getSelectedIndex() < 2)) {
				int idx = srcOrderList.getSelectedIndex();
				GlossarySortCriteria.WithDirection el = srcModel.getElementAt(idx);
				srcModel.remove(idx); srcModel.add(idx + 1, el);
			}
		});
		btnSrcReverse.addActionListener(ev -> { 
			if (srcOrderList.getSelectedIndex() >= 0) {
				int idx = srcOrderList.getSelectedIndex();
				GlossarySortCriteria.WithDirection el = srcModel.getElementAt(idx);
				el.desc = ! el.desc; if (el.desc) btnSrcReverse.setLabel("^ ASC"); else btnSrcReverse.setLabel("v DESC");
				srcOrderList.repaint();
			}
		});
		final javax.swing.DefaultListModel<GlossarySortCriteria.WithDirection> traModel = new javax.swing.DefaultListModel();
		bSortOrder.add (traOrderList = new javax.swing.JList(traModel));
		Box bSortButtonsTra = Box.createVerticalBox(); bSortOrder.add(bSortButtonsTra);
		javax.swing.JButton btnTraUp, btnTraDown, btnTraReverse;
		bSortButtonsTra.add(btnTraUp = new javax.swing.JButton("^ UP")); bSortButtonsTra.add(btnTraDown = new javax.swing.JButton("v DOWN")); bSortButtonsTra.add(btnTraReverse = new javax.swing.JButton("v DESC"));
		btnTraUp.addActionListener(ev -> { 
			if (traOrderList.getSelectedIndex() > 0) {
				int idx = traOrderList.getSelectedIndex();
				GlossarySortCriteria.WithDirection el = traModel.getElementAt(idx);
				traModel.remove(idx); traModel.add(idx - 1, el);
			}
		});
		btnTraDown.addActionListener(ev -> { 
			if ((traOrderList.getSelectedIndex() >= 0) && (traOrderList.getSelectedIndex() < 2)) {
				int idx = traOrderList.getSelectedIndex();
				GlossarySortCriteria.WithDirection el = traModel.getElementAt(idx);
				traModel.remove(idx); traModel.add(idx + 1, el);
			}
		});
		btnTraReverse.addActionListener(ev -> { 
			if (traOrderList.getSelectedIndex() >= 0) {
				int idx = traOrderList.getSelectedIndex();
				GlossarySortCriteria.WithDirection el = traModel.getElementAt(idx);
				el.desc = ! el.desc; if (el.desc) btnTraReverse.setLabel("^ ASC"); else btnTraReverse.setLabel("v DESC");
				traOrderList.repaint();
			}
		});		
			
        this.add (modeBox, BorderLayout.CENTER);
        
        org.openide.awt.Mnemonics.setLocalizedText(okButton, OStrings.getString("BUTTON_OK")); // NOI18N
        okButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                okButtonActionPerformed(evt);
            }
        });
        javax.swing.JPanel pButtons = new javax.swing.JPanel();
        this.add (pButtons, BorderLayout.SOUTH); 
        pButtons.add (buttonsBox, BorderLayout.EAST);        
        buttonsBox.add(okButton);

        org.openide.awt.Mnemonics.setLocalizedText(cancelButton, OStrings.getString("BUTTON_CANCEL")); // NOI18N
        cancelButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelButtonActionPerformed(evt);
            }
        });
        buttonsBox.add(cancelButton);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void okButtonActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_okButtonActionPerformed
    {
        modeBox.savePreferences (Preferences.TRANSTIPS + "_");
        Preferences.setPreference(Preferences.TRANSTIPS_SRC, activeSrc.isSelected());
        Preferences.setPreference(Preferences.TRANSTIPS_TRA, activeTra.isSelected());
        Preferences.setPreference(Preferences.TRANSTIPS_SUGGEST, suggest.isSelected());
        Preferences.setPreference(Preferences.GLOSSARY_PANE_DO_MERGE, cbDoMerge.isSelected());
        Preferences.setPreference(Preferences.GLOSSARY_PANE_TEMPLATE, ((ScriptItem) templateList.getSelectedItem()).toOption());
		org.omegat.gui.glossary.GlossaryEntryView.engine = null; // force re-evaluation
        Preferences.setPreference(Preferences.GLOSSARY_REMOVE_TAGS, ignoreTags.isSelected());
        Preferences.setPreference(Preferences.GLOSSARY_REMOVE_SUBWORDS, removeSubwords.isSelected());

        StringBuffer sortOrderSpec = new StringBuffer();
        for (int i = 0; i < srcOrderList.getModel().getSize(); i++) sortOrderSpec.append(srcOrderList.getModel().getElementAt(i).shortName());
        sortOrderSpec.append(";");
        for (int i = 0; i < traOrderList.getModel().getSize(); i++) sortOrderSpec.append(traOrderList.getModel().getElementAt(i).shortName());
        Preferences.setPreference(Preferences.GLOSSARY_PANE_SORT_ORDER, sortOrderSpec);
		
        doClose(RET_OK);
    }// GEN-LAST:event_okButtonActionPerformed

    private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt)// GEN-FIRST:event_cancelButtonActionPerformed
    {
        doClose(RET_CANCEL);
    }// GEN-LAST:event_cancelButtonActionPerformed

    /** Closes the dialog */
    private void closeDialog(java.awt.event.WindowEvent evt)// GEN-FIRST:event_closeDialog
    {
        doClose(RET_CANCEL);
    }// GEN-LAST:event_closeDialog

    private void doClose(int retStatus) {
        returnStatus = retStatus;
        setVisible(false);
        dispose();
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton okButton;
    private javax.swing.JButton cancelButton;
    private javax.swing.JCheckBox activeSrc, activeTra, ignoreTags, removeSubwords;
    private SearchModeBox modeBox;
    private javax.swing.JCheckBox suggest, cbDoMerge;
    private javax.swing.JComboBox templateList;
    private javax.swing.JList<GlossarySortCriteria.WithDirection> srcOrderList, traOrderList;
    // End of variables declaration//GEN-END:variables

    private int returnStatus = RET_CANCEL;
}
