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

 Copyright (C) 2010 Wildrich Fourie, Alex Buloichik, Didier Briel
               2011 Didier Briel
               2012 Thomas Cordonnier
               2015-2016 Thomas Cordonnier
               Home page: http://www.omegat.org/
               Support center: http://groups.yahoo.com/group/OmegaT/

 This file is part of OmegaT.

 OmegaT 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 3 of the License, or
 (at your option) any later version.

 OmegaT 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, see <http://www.gnu.org/licenses/>.
 **************************************************************************/

package org.omegat.gui.glossary;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.omegat.util.Preferences;

import org.omegat.core.Core;
import org.omegat.core.search.TextExpression;
import org.omegat.core.search.SearchMatch;
import org.omegat.core.glossaries.GlossaryEntryStore;
import org.omegat.tokenizer.ITokenizer;
import org.omegat.gui.search.SearchModeBox;
import org.omegat.tokenizer.ITokenizer;

/**
 * Underlines all the terms in the SourceTextEntry that has matches in the
 * Glossary.
 * 
 * @author W. Fourie
 * @author Alex Buloichik
 * @author Didier Briel
 * @author Thomas Cordonnier
 */
public class TransTips {
    /**
     * Search for a word and returns the offset of the first occurrence.
     * Highlights are added for all occurrences found.
     * 
     * @param glossaryEntry
     *            To be searched
     * @param start
     *            Starting position
     * @param end
     *            Ending position
     * @return The offset of the first occurrence
     */
    public static void search(String sourceText, GlossaryEntryStore glossaryEntry, Search callback, boolean isSource) {
        if (isSource) searchPhrase(sourceText, glossaryEntry, glossaryEntry.getSrcText(), callback, true);
        else
            for (String tra: glossaryEntry.getLocTerms(true)) searchPhrase(sourceText, glossaryEntry, tra, callback, false);
	}
	
	private static void searchPhrase(String sourceText, GlossaryEntryStore glossaryEntry, String phrase, Search callback, boolean isSource) {
        if (phrase == null || phrase.equals("")) return;   // Test for invalid word.     

        SearchModeBox dummyBox = new SearchModeBox (0, ITokenizer.StemmingMode.GLOSSARY, null);
        dummyBox.loadPreferences (Preferences.TRANSTIPS + "_");
        TextExpression expr = dummyBox.buildExpression(phrase, false, isSource);
		
        List<Integer> startTags = null, endTags = null; 
        if (Preferences.isPreferenceDefault(Preferences.GLOSSARY_REMOVE_TAGS, false)) {
            startTags = new ArrayList<>(); endTags = new ArrayList();
            Matcher m = Pattern.compile("</?\\w+/?>").matcher(sourceText); while (m.find()) { startTags.add(m.start()); endTags.add(m.end()); }			
            sourceText = sourceText.replaceAll("</?\\w+/?>", "");
        }
        
        List<SearchMatch> matches = expr.searchString (sourceText);
        if (matches == null) return;
        else if (startTags != null)
            for (int i = 0; i < matches.size(); i++) {
            TAGS_1:
                for (int j = 0; j < startTags.size(); j++) {
                    if (startTags.get(j) <= matches.get(i).getStart())
                        matches.get(i).move (endTags.get(j) - startTags.get(j));
                    else
                        break TAGS_1;
                }
            TAGS_2:
                for (int j = 0; j < startTags.size(); j++) {
                    if (startTags.get(j) > matches.get(i).getStart()) 
                        if (startTags.get(j) < matches.get(i).getEnd())
                            matches.get(i).addLength (endTags.get(j) - startTags.get(j));
                        else 
                            break TAGS_2;
                }
            }
        for (SearchMatch found: matches)
            callback.found(glossaryEntry, found.getStart(), found.getEnd());
    }

    public interface Search {
        void found(GlossaryEntryStore glossaryEntry, int start, int end);
    }
}
