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

 Copyright (C) 20107 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.search;

import java.util.List;
import java.util.ArrayList;

/**
 * Extends search match for regular expression replacement:
 * we must store the text for replacement because it will differ from one target string to another
 *
 * @author Thomas Cordonnier (t_cordonnier@yahoo.fr)
 */
public class ReplaceMatch extends SearchMatch {
    private String replacement;

    public ReplaceMatch(int start, int end, String replacement) {
        super(start, end);
        this.replacement = replacement;
    }
    
    public final String getReplacement() {
        return replacement;
    }

    /**
     * Merge current object with an other one
     * 
     * @param other
     *           Other search match to merge with
     * @param mustKeep
     *           If true, always returns a new object; else, try to modify current object and return this
     * @param defaultReplacement
     *           If merged with a replace match, the text to be put in the place of current one.
     * 
     * @return merged object
     */
	@Override
    public ReplaceMatch merge(SearchMatch other, boolean mustKeep, String defaultReplacement) {
        String rightPart; try { rightPart = ((ReplaceMatch) other).replacement; } catch (ClassCastException cce) { rightPart = defaultReplacement; }
        if (mustKeep) return new ReplaceMatch (Math.min (this.start, other.start), Math.max(this.end, other.end), this.replacement + rightPart);
        else {
            this.start = Math.min (this.start, other.start); this.end = Math.max(this.end, other.end); 
            this.replacement += rightPart;
            return this;
        }
    }

    /** Returns a match where the words are kept entirely **/
    public SearchMatch englobeWord(String source) {
        int newStart = this.start, newEnd = this.end;
        while ((newStart > 0) && (Character.isLetter(source.charAt(newStart - 1)))) newStart--; 
        while ((newEnd < source.length()) && (Character.isLetter(source.charAt(newEnd)))) newEnd++;
        return new ReplaceMatch (newStart, newEnd, this.replacement);	// new bounds, same replacement
    }
    
    /** 
     * Calculate the string where all matches are replaced 
     *
     * @param ori	The string without replacements
     * @param matches		List of search/replace matches to apply
     * @param defaultReplacement	Default replacement for non-replace matches
     **/
    public static String buildReplacedString (String ori, List<SearchMatch> matches, String defaultReplacement) {
        int shift = 0;
        for (SearchMatch m0: matches) {
            String repl;
            try { repl = ((ReplaceMatch) m0).replacement; } catch (Exception e) { repl = defaultReplacement; }
            ori = ori.substring (0, m0.start + shift) + repl + ori.substring (m0.end + shift);
            shift += repl.length() - (m0.end - m0.start);
        }
        return ori;
    }
    
    /**
     * Calculate the location of the matches in the replaced string
     *
     * @param ori	The string without replacements
     * @param matches		List of search/replace matches to apply
     * @param defaultReplacement	Default replacement for non-replace matches
     **/
    public static List<SearchMatch> buildReplacedMatches (String ori, List<SearchMatch> matches, String defaultReplacement) {
        int shift = 0; List<SearchMatch> newList = new ArrayList<> (matches.size());
        for (SearchMatch m0: matches) {
            String repl;
            try { repl = ((ReplaceMatch) m0).replacement; } catch (Exception e) { repl = defaultReplacement; }
            int shift2 = repl.length() - (m0.end - m0.start);
            newList.add (new SearchMatch(m0.start + shift, m0.end + shift + shift2));
            shift += shift2;
        }
        return newList;
    }
     
}
