/*
 * RmiClientImpl.java
 *
 * Created on October 15, 2003, 7:02 PM
 */

package hep.aida.ref.remote.rmi.server;

import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.SocketAddress;
import  java.net.UnknownHostException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
import java.text.DateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Hashtable;
import java.util.StringTokenizer;

import hep.aida.ref.ManagedObject;
import hep.aida.ref.remote.interfaces.AidaTreeClient;
import hep.aida.ref.remote.interfaces.AidaTreeServant;
import hep.aida.ref.remote.interfaces.AidaTreeServer;
import hep.aida.ref.remote.interfaces.AidaUpdateEvent;
import hep.aida.ref.remote.rmi.RmiRemoteUtils;
import hep.aida.ref.remote.rmi.converters.RmiConverter;
import hep.aida.ref.remote.rmi.converters.RmiHist1DConverter;
import hep.aida.ref.remote.rmi.interfaces.RmiClient;
import hep.aida.ref.remote.rmi.interfaces.RmiServant;
import hep.aida.ref.remote.rmi.interfaces.RmiServer;

import org.freehep.util.FreeHEPLookup;
import org.openide.util.Lookup;

/**
 *
 * @author  serbo
 */
public class RmiServantImpl extends UnicastRemoteObject implements RmiServant, AidaTreeClient {
    
    static final long serialVersionUID = 5141620123191080485L;
    private RmiClient rmiClient;
    private AidaTreeServant aidaServant;
    private Map converters;
    
    /** Creates a new instance of RmiClientImpl */
    public RmiServantImpl() throws RemoteException {
        this(null, null);
    }
    
    public RmiServantImpl(RmiClient rmiClient) throws RemoteException {
        this(rmiClient, null);
    }

    public RmiServantImpl(AidaTreeServant aidaServant) throws RemoteException {
        this(null, aidaServant);
    }

    public RmiServantImpl(RmiClient rmiClient, AidaTreeServant aidaServant) throws RemoteException {
        super();
        this.rmiClient = rmiClient;
        this.aidaServant = aidaServant;
        converters = new Hashtable();        
        connect();
    }
    
    
    // Service methods
    
    void connect() {
    }
    
    void setAidaTreeServant(AidaTreeServant aidaServant) {
        this.aidaServant = aidaServant;
    }
    
    void setRmiClient(RmiClient rmiClient) {
        this.rmiClient = rmiClient;
    }
    
    void disconnect() {
	try {
	    unexportObject(this, true);
	} catch (Exception e2) { e2.printStackTrace(); }
        
        rmiClient = null;
        aidaServant = null;
    }
    
    protected RmiConverter findConverter(String aidaType) {
        RmiConverter converter = null;
        if (converters.containsKey(aidaType)) {
            converter = (RmiConverter) converters.get(aidaType);
        } else {
            Lookup.Template template = new Lookup.Template(RmiConverter.class, aidaType, null);
            Lookup.Item item = FreeHEPLookup.instance().lookupItem(template);
            if (item == null) throw new IllegalArgumentException("No Converter for AIDA Type: "+aidaType);

            converter = (RmiConverter) item.getInstance();
            converters.put(aidaType, converter);
        }
        return converter;
        
    }
    
    // RmiServant methods
    
    public java.lang.Object find(String path) throws RemoteException {
        java.lang.Object mo = aidaServant.find(path);
        String aidaType = null;
        if (mo instanceof ManagedObject) aidaType = ((ManagedObject) mo).getAIDAType();
        else aidaType = mo.getClass().getName();

        RmiConverter converter = findConverter(aidaType);
        java.lang.Object data = converter.extractData(mo);
        return data;
    }
    
    public String[] listObjectNames(String path) throws RemoteException {
        return aidaServant.listObjectNames(path);
    }
    
    public String[] listObjectTypes(String path) throws RemoteException {
        return aidaServant.listObjectTypes(path);
    }
    
    public void setValid(String[] nodePaths) throws RemoteException {
        aidaServant.setValid(nodePaths);
    }
    
    public AidaUpdateEvent[] updates() throws RemoteException {
        return aidaServant.updates();
    }
    

    // AidaTreeClient methods
    
    public void stateChanged(AidaUpdateEvent[] events) {
        try {
            rmiClient.stateChanged(events);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    
}
