/*
 * AidaTreeClientTest.java
 *
 * Created on October 15, 2003, 11:46 PM
 */

package hep.aida.ref.remote.testRemote;

import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

import hep.aida.dev.IDevMutableStore;

import hep.aida.ref.remote.RemoteConnectionException;
import hep.aida.ref.remote.RemoteUpdateEvent;
import hep.aida.ref.remote.interfaces.AidaTreeClient;
import hep.aida.ref.remote.interfaces.AidaUpdateEvent;

/**
 * This is a very simple AidaTreeClient that just delegates
 * most of the methods to the TestUtils class.
 *
 * @author  serbo
 */
public class AidaTreeClientTest implements AidaTreeClient {
    
    private Map hash;
    
    private IDevMutableStore store;
    private boolean duplex;
    public static long serverUpdateInterval;
    private boolean connected;
    private Thread thread;
    private boolean keepRunning;
    private String nodeType = "RemoteManagedObjectTest";
    
    /** Creates a new instance of AidaTreeClientTest */
    public AidaTreeClientTest(IDevMutableStore store) {
        this(store, true);
    }
    
    public AidaTreeClientTest(IDevMutableStore store, boolean duplex) {
        this(store, duplex, -1);
    }
    
    public AidaTreeClientTest(IDevMutableStore store, boolean duplex, long serverUpdateInterval) {
        this.store = store;
        this.duplex = duplex;
        this.serverUpdateInterval = serverUpdateInterval;
        initTestClient();
    }
    
    
    // Service methods
    
    public void initTestClient() {
        this.connected = false;
        if (hash != null) hash.clear();
        else hash = new Hashtable();
        keepRunning = true;
        if (duplex && serverUpdateInterval > 0) startUpdateThread();
    }
    
    // Start separate thread to notify Store about updates
    // for all known objects. This simulates updates comming
    // from the remote server.
    public void startUpdateThread() {
        thread = new Thread(new Runnable() {
            public void run() {
                while (keepRunning) {
                    try { 
                        Thread.sleep(serverUpdateInterval);
                    } catch (Exception e) { e.printStackTrace(); }
                    synchronized (hash) {
                        if (!hash.isEmpty()) {
                            int size = hash.size();
                            AidaUpdateEvent[] events = new AidaUpdateEvent[size];
                            int i = 0;
                            Iterator it = hash.keySet().iterator();
                            while (it.hasNext()) {
                                String path = ((String) it.next());
                                events[i] = new RemoteUpdateEvent(AidaUpdateEvent.NODE_UPDATED, path, nodeType);
                                i++;
                            }
                            stateChanged(events);
                        }
                    } // End synchronized
                }
            }
        });  
        thread.start();
    }
    
    
    
    // AidaTreeClient methods
    
    public boolean connect() throws RemoteConnectionException {
        if (!connected) connected = true;
        else throw new RemoteConnectionException("Already connected, please disconnect first!");
        
        return connected;
    }
    
    public boolean disconnect() {
        serverUpdateInterval = 1;
        keepRunning = false;
        connected = false;
        if (hash != null) hash.clear();
        hash = null;
        thread = null;
        return true;
    }
    
    public java.lang.Object find(String path) throws IllegalArgumentException {
        Object obj = TestUtils.find(path);
        hash.put(path, obj);        
        return obj;
    }
    
    public boolean isConnected() {
        return connected;
    }
    
    public String[] listObjectNames(String path) throws IllegalArgumentException {
        return TestUtils.listObjectNames(path);   
    }
    
    public String[] listObjectTypes(String path) throws IllegalArgumentException {
        return TestUtils.listObjectTypes(path); 
    }
    
    // Just call store method to update data for the object
    public void stateChanged(AidaUpdateEvent[] events) {
        //System.out.println("AidaTreeClientTest.stateChanged  got "+events.length+"  updates");
        for (int i=0; i<events.length; i++) {
            String path = events[i].path();
            String type = events[i].nodeType();
            //System.out.println("\t*** "+i+"   "+path+"   "+type);
            store.updateData(path,type);
        }
    }
    
    
}
