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

 Copyright (C) 2014 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.external.rmi;

import org.omegat.core.data.*;
import org.omegat.core.Core;
import org.omegat.core.CoreEvents;

import org.omegat.core.matching.external.ProjectMemory.ContextTMXEntry;
import org.omegat.core.events.IEntryEventListener;

import java.util.*;
import java.rmi.*;

/** Identical to ProjectMemory.IExternalMemory but is a remote interface **/
public class Server extends java.rmi.server.UnicastRemoteObject implements IDistantExternalMemory, IEntryEventListener {

    public Server() throws RemoteException {
        CoreEvents.registerEntryEventListener(this);
    }

    // -------------------- IEntryEventListener -------------
    
    private Set<Integer> changes = new HashSet<Integer>();
    private Set<SourceTextEntry> used = new HashSet<SourceTextEntry>();
    
    public void onNewFile(String activeFileName) {}
    
    public void onEntryActivated(SourceTextEntry newEntry) {
        try {
            if (changes.size() > 0) {
                int num = Core.getEditor().getCurrentEntryNumber();
                try {
                    for (int id: changes)
                        Core.getEditor().gotoEntry(id);
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
                Core.getEditor().gotoEntry(num);
            }
            changes.clear();
        } catch (Exception e) {
            e.printStackTrace();
        }
        used.add (newEntry);
    }

    // ------------------ IDistantExternalMemory -------------
    
    /**
     * Sent by any client which wants to get the changes
     **/
    public List<ContextTMXEntry> findChanges (final long timeStamp) throws RemoteException {
        IProject proj = Core.getProject();
        if (! (proj instanceof RealProject)) return Collections.EMPTY_LIST;
        
        // Optimisation : since the client is started after the server, if an entry has changed it has been activated before
        final Collection<SourceTextEntry> usedEntries =
            timeStamp == 0 ? Core.getProject().getAllEntries()
                : this.used.isEmpty() ? Core.getProject().getAllEntries()
                : this.used;
        final List<ContextTMXEntry> res = new ArrayList<ContextTMXEntry>(usedEntries.size());
        for (SourceTextEntry sourceEntry: usedEntries) {
            TMXEntry trans = proj.getTranslationInfo(sourceEntry);
            if ((trans.changeDate < timeStamp) && (trans.creationDate < timeStamp)) continue;
            // Still here? Add the entry
            if (! trans.isTranslated()) res.add (new ContextTMXEntry(sourceEntry, trans.defaultTranslation)); // entry for deletion
            else res.add (new ContextTMXEntry(trans, sourceEntry)); // entry modified
        }
        return res;
    }

    /**
     * Sent by a client, adds the translation in local project memory (in memory, not saved)
     */
    public void registerTranslation(ContextTMXEntry entry) throws RemoteException {
        int num = entry.entryNum - 1; changes.add (num);
        SourceTextEntry ste = Core.getProject().getAllEntries().get(num); used.add (ste);
        Core.getProject().setTranslation(ste, (PrepareTMXEntry) entry, entry.isDefault, entry.linked);
    }

    /**
     * Sent by a client, removes translation in local project memory (in memory, not saved)
     */
    public void removeTranslation(ContextTMXEntry entry) throws RemoteException {
        int num = entry.entryNum - 1; changes.add (num);
        SourceTextEntry ste = Core.getProject().getAllEntries().get(num); used.add (ste);
        Core.getProject().setTranslation(ste, (PrepareTMXEntry) entry, entry.isDefault, entry.linked);
    }

    public long timeStamp() throws RemoteException {
        return System.currentTimeMillis();
    }
}
