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

 Copyright (C) 2000-2006 Keith Godfrey and Maxym Mykhalchuk
               2006 Henry Pijffers
               2009 Didier Briel
               2010 Martin Fleurke, Antonio Vilei, Didier Briel
               2012 Didier Briel, Thomas Cordonnier
               2015-2021 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.search;

import java.io.File;
import java.util.Set;
import java.util.TreeSet;

import java.awt.Color;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.Box;
import javax.swing.text.JTextComponent;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import org.openide.awt.Mnemonics;

import org.omegat.filters2.master.FilterMaster;
import org.omegat.gui.main.MainWindow;
import org.omegat.util.Log;
import org.omegat.util.Preferences;
import org.omegat.util.OStrings;
import org.omegat.util.StringUtil;
import org.omegat.util.StaticUtils;
import org.omegat.util.gui.OmegaTFileChooser;
import org.omegat.core.data.ProjectOptions;
import org.omegat.core.search.Searcher;
import org.omegat.core.search.DirectorySearcher;
import org.omegat.core.Core;

import gen.core.filters.Filters;

/**
 * This is a window that appears when user'd like to search for something. For
 * each new user's request new window is created. Actual search is done by
 * SearchThread.
 * 
 * @author Keith Godfrey
 * @author Henry Pijffers (henry.pijffers@saxnot.com)
 * @author Didier Briel
 * @author Martin Fleurke
 * @author Antonio Vilei
 * @author Thomas Cordonnier
 */
@SuppressWarnings("serial")
public class DirectorySearchWindow extends SearchWindow {
    private static final java.util.Map<String,Set<String>> theMap = new java.util.HashMap<String,Set<String>>();
    static {		
        for (String mode: new String[] { "EXACT", "KEYWORD", "REGEXP" })
            theMap.put ("SW_SEARCH_TEXT:" + mode, new TreeSet<String>());
        org.omegat.core.CoreEvents.registerProjectChangeListener(new SearchesLoader<Set<String>>("DirectorySearchWindow", theMap));
    }
    
    private SetRef setRef;
    public void refreshLists(boolean removeContents) {
        String selected = removeContents ? "" : m_searchField.getSelectedItem().toString();
        m_searchField.removeAllItems();
        m_searchField.addItem (selected);
        setRef.theSet = theMap.get("SW_SEARCH_TEXT:" + m_modePanel.searchTypeString());
        for (String item: setRef.theSet) m_searchField.addItem(SearchModeBox.MemorizedExpression.forString(item));
        m_searchField.setSelectedItem (selected);		
    }
    
    public DirectorySearchWindow(MainWindow par, String startText) {
        super(par, startText);
        refreshLists(true); // after all components, in particular the m_modePanel, have been built
        if (startText != null) m_searchField.setSelectedItem(startText);
        JTextComponent searchFieldArea = (JTextComponent) m_searchField.getEditor().getEditorComponent();
        searchFieldArea.addMouseListener(new org.omegat.gui.editor.PopupMenuDisplayer(searchFieldArea));
        m_modePanel.addModeChangeListener(new RegexModeSwitchListener(m_modePanel, searchFieldArea));
        this.options = Core.getProject().getProjectProperties();
    }
    
    public DirectorySearchWindow(ProjectOptions options, File destDir, String startText) {
        super(null, startText);
        this.options = options;
        refreshLists(true); // after all components, in particular the m_modePanel, have been built
        if (startText != null) m_searchField.setSelectedItem(startText);
        JTextComponent searchFieldArea = (JTextComponent) m_searchField.getEditor().getEditorComponent();
        searchFieldArea.addMouseListener(getPopupFactory(searchFieldArea));
        m_modePanel.addModeChangeListener(new RegexModeSwitchListener(m_modePanel, searchFieldArea));
        if (destDir != null) m_dirField.setText(destDir.toString());
    }
    
    public static void main(String[] args) {
        if (args.length < 1) {
            System.err.println("Syntax: java -cp OmegaT.jar org.omegat.gui.search.DirectorySearchWindow [source lang] [target lang]? [directory]? [text]?");
            System.exit(1);
        }
        // Configuration
        org.omegat.filters2.master.PluginUtils.loadPlugins(null);
        Filters filterMasterConfig = FilterMaster.loadConfig(StaticUtils.getConfigDir());
        if (filterMasterConfig == null) filterMasterConfig = FilterMaster.createDefaultFiltersConfig();
        Core.setFilterMaster(new FilterMaster(filterMasterConfig));
        // Action
        ProjectOptions opt = new ProjectOptions();
        opt.setSourceLanguage(args[0]);
        if (args.length > 1) opt.setTargetLanguage(args[1]);
        File destDir = null; if (args.length > 2) destDir = new File(args[2]);
        String text = null; if (args.length > 3) destDir = new File(args[3]);
        DirectorySearchWindow dsw = new DirectorySearchWindow(opt, destDir, text);
        dsw.setDefaultCloseOperation(EXIT_ON_CLOSE); dsw.setVisible(true);
    }
    
    // Build help text
    protected String getScopeText() { return OStrings.getString("SW_HELP_SCOPE_DIRECTORY"); }
    protected boolean isReplace() { return false; }        
    
    @Override
    protected JComponent textPanel(String startText) {
        JLabel m_searchLabel = new JLabel();
        Mnemonics.setLocalizedText(m_searchLabel, OStrings.getString("SW_SEARCH_TEXT"));
        m_searchField = new JComboBox(); m_searchField.setEditable(true);
		m_searchField.addActionListener (ev -> {
			try {
				SearchModeBox.MemorizedExpression item = (SearchModeBox.MemorizedExpression) m_searchField.getSelectedItem();
				item.applyTo(DirectorySearchWindow.this.m_modePanel);
			} catch (Exception cce) { // ClassCast | NullPointer
				
			}
		});

        if (startText != null) m_searchField.setSelectedItem(startText);
        Box bSearch = Box.createHorizontalBox();
        bSearch.add(m_searchLabel);
        bSearch.add(m_searchField);
        bSearch.add(this.createMemorizeButton(
            DirectorySearchWindow.this.getY(), true, m_searchField, null, 
            "SW_SEARCH_TEXT", setRef = new SetRef(theMap.get("SW_SEARCH_TEXT:EXACT"))
        ));
        bSearch.add(Box.createHorizontalStrut(H_MARGIN));
        bSearch.setBorder (BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.black), OStrings.getString("SW_ZONE_TEXT")));
        
        return bSearch;
    }
    
    public JComboBox getMainSearchTextField() {
        return m_searchField;
    }
    
    protected String[] getFormatVariablesList() {
        return new String[] {
            SearchVarExpansion.VAR_PREAMBLE, SearchVarExpansion.VAR_CREATION_ID, SearchVarExpansion.VAR_CREATION_DATE,
            SearchVarExpansion.VAR_SOURCE_TEXT, 
            SearchVarExpansion.VAR_FILE_NAME, SearchVarExpansion.VAR_FILE_NAME_ONLY, SearchVarExpansion.VAR_FILE_PATH, SearchVarExpansion.VAR_FILE_SHORT_PATH
        };
    }
    
    protected String getFormatOptionName() {
        return Preferences.SEARCHWINDOW_TEMPLATE_DIRECTORY;
    }
    protected String getFormatOptionDefaultValue() {
        return SearchVarExpansion.DEFAULT_TEMPLATE_DIRECTORY;
    }
    
    @Override
    public Box wherePanel() {
        // box Directory bDir
        JLabel m_dirLabel = new JLabel();
        Mnemonics.setLocalizedText(m_dirLabel, OStrings.getString("SW_LOCATION"));
        m_dirField = new JTextField(50);
        m_dirField.setEditable(false);
        m_dirField.setMaximumSize(new java.awt.Dimension(Integer.MAX_VALUE, getPreferredSize().height));
        m_dirButton = new JButton();
        Mnemonics.setLocalizedText(m_dirButton, OStrings.getString("SW_BROWSE"));
        m_recursiveCB = new JCheckBox();
        Mnemonics.setLocalizedText(m_recursiveCB, OStrings.getString("SW_DIR_RECURSIVE"));
        m_recursiveCB.setSelected(true);
        Box bDir = Box.createHorizontalBox();
        bDir.add(m_dirLabel);
        bDir.add(m_dirField);
        bDir.add(Box.createHorizontalStrut(H_MARGIN));
        bDir.add(m_dirButton);
        bDir.add(m_recursiveCB);
        bDir.add(Box.createHorizontalGlue());
        bDir.setBorder (BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.black), OStrings.getString("SW_LOCATION")));        
        m_dirButton.addActionListener(e -> { doBrowseDirectory(); });	
        
        return bDir;
    }	
    
    @Override
    protected void loadPreferences() {
        super.loadPreferences();

        // search dir options
        String searchDir = Preferences.getPreference(Preferences.SEARCHWINDOW_DIR);
        if (!StringUtil.isEmpty(searchDir))
            m_dirField.setText(searchDir);
        m_dirField.setEditable(true);
        String recursive = Preferences.getPreference(Preferences.SEARCHWINDOW_RECURSIVE);
        if (StringUtil.isEmpty(recursive))
            recursive = "true";
        m_recursiveCB.setSelected(Boolean.valueOf(recursive).booleanValue());
    }
    
    protected void savePreferences() {
        super.savePreferences();
        
        // search dir options
        Preferences.setPreference(Preferences.SEARCHWINDOW_DIR, m_dirField.getText());
        Preferences.setPreference(Preferences.SEARCHWINDOW_RECURSIVE,
                Boolean.toString(m_recursiveCB.isSelected()));

        // need to explicitly save preferences
        // because project might not be open
        Preferences.save();
    }

    private void doBrowseDirectory() {
        OmegaTFileChooser browser = new OmegaTFileChooser();
        // String str = OStrings.getString("BUTTON_SELECT");
        // browser.setApproveButtonText(str);
        browser.setDialogTitle(OStrings.getString("SW_TITLE_SEARCH"));
        browser.setFileSelectionMode(OmegaTFileChooser.DIRECTORIES_ONLY);
        String curDir = m_dirField.getText();

        if (!curDir.equals("")) {
            File dir = new File(curDir);
            if (dir.exists() && dir.isDirectory()) {
                browser.setCurrentDirectory(dir);
            }
        }

        browser.showOpenDialog(this);
        File dir = browser.getSelectedFile();
        if (dir == null)
            return;

        String str = dir.getAbsolutePath() + File.separator;
        m_dirField.setText(str);
    }

    @Override
    protected DirectorySearcher buildSearcher(Searcher previous) throws IllegalArgumentException {
        String root = m_dirField.getText();
        if (!root.endsWith(File.separator)) root += File.separator;
        File f = new File(root);
        if (!f.exists() || !f.isDirectory()) {
            String error = String.format(OStrings.getString("SW_ERROR_BAD_DIR"), 
                new Object[] { m_dirField.getText() });
            throw new IllegalArgumentException(error);
        }

        if ((m_searchField.getSelectedItem() == null) || (m_searchField.getSelectedItem().toString().length() == 0)) throw new IllegalArgumentException(OStrings.getString("SW_ERROR_MANDATORY_FIELD_SEARCH"));

        // start the search in a separate thread
        return new DirectorySearcher (this, options == null ? Core.getProject().getProjectProperties() : options, 
            m_modePanel.buildExpression(m_searchField.getSelectedItem().toString(), false, true), 
            m_removeDupCB.isSelected(), ((Integer) m_numberOfResults.getValue()),
            root, m_recursiveCB.isSelected());
    }
    
    protected JComponent[] componentsEnabledWhenResults() {
        return new JComponent[0];
    }
    
    protected JTextComponent[] textFieldsList() {
        return new JTextComponent[0];
    }
    
    protected ProjectOptions getOptions() { return options == null ? Core.getProject().getProjectProperties() : options; }
    
    private ProjectOptions options = null;
    private JComboBox m_searchField;
    private JTextField m_dirField;
    private JButton m_dirButton;
    private JCheckBox m_recursiveCB;
    
}
