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

 Copyright (C) 2020 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.core.matching;

import java.util.List;

import org.omegat.core.data.EntryKey;
import org.omegat.core.data.IProject;
import org.omegat.core.events.IStopped;
import org.omegat.core.matching.external.IExternalMemory;
import org.omegat.tokenizer.ITokenizer;
import org.omegat.util.OConsts;
import org.omegat.util.TMXProp;
import org.omegat.util.Preferences;

/**
 * Matcher which keeps only top match
 *
 * @author Thomas Cordonnier
 */
public class FindMatchesSingleton extends FindMatchesKeep {    
    private NearString result = null;

    public FindMatchesSingleton(ITokenizer sourceTokenizer, final IExternalMemory[] externalMemories, String memoryPath, boolean allowSeparateSegmentMatch, boolean searchExactlyTheSame) {
        super(sourceTokenizer, externalMemories, memoryPath, allowSeparateSegmentMatch, searchExactlyTheSame); 
    }
    
    /**
     * @param searchExactlyTheSame
     *            allows to search similarities with the same text as source segment. This mode used only for
     *            separate sentence match in paragraph project, i.e. where source is just part of current
     *            source.
     */
    public FindMatchesSingleton(ITokenizer sourceTokenizer, final IExternalMemory[] externalMemories, boolean allowSeparateSegmentMatch, boolean searchExactlyTheSame) {
        super(sourceTokenizer, externalMemories, allowSeparateSegmentMatch, searchExactlyTheSame);
    }
    
    @Override public final int maxCount() { return 1; }    
    @Override protected NearString lastKeptResult() { return result; }

    public NearString search(final IProject project, final String searchText,
            final boolean requiresTranslation, final boolean fillSimilarityData, final IStopped stop)
            throws StoppedException {
        result = null;
        doSearch(project, searchText, requiresTranslation, fillSimilarityData, stop);
        
        if (fillSimilarityData)
            // fill similarityStem data only for result
            buildSimilarityData(result);
        
        return result;
    }
    
    
    /**
     * Compare one entry with original entry.
     * 
     * @param candEntry
     *            entry to compare
     */
    protected void doInsertion(final NearString added) {
       /**
        * Replace result if score is higher. Using sort key selected by user
        */
        
        if (result == null) { result = added; return; }

        if ((result != null) && Preferences.isPreferenceDefault(Preferences.EXT_TMX_MERGE, true) && added.source.equals(result.source)
                && (added.translation == null && result.translation == null || added.translation != null
                && added.translation.equals(result.translation))) {
            // Consolidate identical matches from different sources into a single NearString with
            // multiple project entries.
            result = NearString.merge(result, added);
            return;
        }
        
        if (result.composedScoreForSorting(this.sortKey) < added.composedScoreForSorting(this.sortKey)) result = added;
    }
}
