/**************************************************************************
 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 Thomas Cordonnier
               2017 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.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.gui.OmegaTFileChooser;
import org.omegat.core.search.DirectorySearcher;
import org.omegat.core.Core;

/**
 * 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 PopupFactory(searchFieldArea));
        m_modePanel.addModeChangeListener(new RegexModeSwitchListener(m_modePanel, searchFieldArea));
    }
    
    // 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() throws Exception {
        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 Exception(error);
        }

		if ((m_searchField.getSelectedItem() == null) || (m_searchField.getSelectedItem().toString().length() == 0)) throw new Exception(OStrings.getString("SW_ERROR_MANDATORY_FIELD_SEARCH"));
		
        // start the search in a separate thread
        return new DirectorySearcher (this, Core.getProject().getProjectProperties(), 
            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];
	}
    
    private JComboBox m_searchField;
    private JTextField m_dirField;
    private JButton m_dirButton;
    private JCheckBox m_recursiveCB;
    
}
