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

 Copyright (C) 2010 Antonio Vilei
               2012 Thomas Cordonnier
               2014 Piotr Kulik
               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.core.search;

import java.util.Date;
import java.util.List;

import org.omegat.util.TMXProp;
import org.omegat.util.OStrings;


/**
 * Storage for a search result entry.
 * 
 * @author Antonio Vilei
 * @author Thomas Cordonnier
 */
public abstract class SearchResultEntry implements Comparable<SearchResultEntry> {

    /**
     * Fills matches parts
     * 
     * @param srcMatch
     *            What has been found in source
     * @param target
     *            What has been found in target
     * @param note
     *            What has been found in note
     */
    protected SearchResultEntry(List<SearchMatch> srcMatch, List<SearchMatch> targetMatch, List<SearchMatch> noteMatch) {
        m_srcMatch = srcMatch;
        m_targetMatch = targetMatch;
        m_noteMatch = noteMatch;
    }

    /**
     * Returns the number of the corresponding entry within a project. The
     * returned value is > 0 if the entry belongs to one of the source files of
     * the project; it is -1 if the entry doesn't belong to any of the source
     * files (the entry is stored in the TM or we are searching in a given
     * directory)
     */
    public abstract int getEntryNum();

    /** Returns information about where this entry comes from. */
    public abstract String getPreamble();
    
    /** Returns the source text of the corresponding entry within a project. */
    public abstract String getSrcText();

    /** Returns the target text of the corresponding entry within a project. */
    public abstract String getTranslation();

    /** Returns the note text of the corresponding entry within a project. */
    public abstract String getNote();

    public abstract String getFileName();
    
    public abstract String getAuthor();
    
    public abstract String getRevisor();
    
    public abstract Date getDate();

    public abstract List<TMXProp> getProperties();

    public List<SearchMatch> getSrcMatch() {
        return m_srcMatch;
    }

    public List<SearchMatch> getTargetMatch() {
        return m_targetMatch;
    }

    public List<SearchMatch> getNoteMatch() {
        return m_noteMatch;
    }

    /** Is duplicate? True if same source and target **/
    public boolean equals (SearchResultEntry entry) {
        if (! entry.getSrcText().equals (getSrcText())) return false;
        if (getTranslation() == null) return entry.getTranslation() == null;
        return getTranslation().equals (entry.getTranslation());
    }
    
    /** 
     * Entries are sorted like this :
     * First, work entries, ordered by number; 
     * Then, other entries, ordered by file name, source and target text.
     **/
    public final int compareTo (SearchResultEntry other) {
        if (this.getEntryNum() > 0)
            if (other.getEntryNum() > 0) return this.getEntryNum() - other.getEntryNum();
            else return -1; // this < other: other entries always come after working ones
        else
            if (other.getEntryNum() > 0) return +1; // other < this: other is internal so it comes before
            else return this.compareContents(other); // two external entries: use other comparator
    }

    protected int compareContents (SearchResultEntry other) {
        int compare = getFileName().compareTo (other.getFileName());
        if (compare != 0) return compare;
        compare = getSrcText().compareTo (other.getSrcText());
        if (compare != 0) return compare;
        if ((getTranslation() != null) && (other.getTranslation() != null)) compare = getTranslation().compareTo (other.getTranslation());
        return 0;
    }
    
    private int more = 0;
    
    void addMore() { more++; }		// can only be called from package
    
    public final String getMoreString() {
        if (more == 0) return "";
        return "\u00A0(" + OStrings.getString("SW_NR_OF_MORE").replace("{0}", Integer.toString(more)) + ")";
    }
    
    private List<SearchMatch> m_srcMatch;
    private List<SearchMatch> m_targetMatch;
    private List<SearchMatch> m_noteMatch;
}
