import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

import org.jgroups.Address;
import org.jgroups.Channel;
import org.jgroups.ExtendedMembershipListener;
import org.jgroups.ExtendedMessageListener;
import org.jgroups.JChannel;
import org.jgroups.Message;
import org.jgroups.View;
import org.jgroups.blocks.PullPushAdapter;
import org.jgroups.util.Util;


public class Comm implements ExtendedMessageListener, ExtendedMembershipListener {
    
	Channel channel;
    PullPushAdapter ad;
	String group_name = "Coll_Paint";
	Collab c;
	
	
	public Comm(Collab cc, String[] a) {
		if (a.length != 0) {group_name = a[0];}
		System.out.println("Group name is " + group_name);
		init();
		c = cc;
	}
	
	private void init() {
        try {
            channel=new JChannel();
            channel.setOpt(Channel.AUTO_RECONNECT, Boolean.TRUE);
            channel.setOpt(Channel.AUTO_GETSTATE, Boolean.TRUE);
            channel.setOpt(Channel.BLOCK, Boolean.TRUE);
            System.out.println("Connecting to " + group_name);
            channel.connect(group_name);
            ad=new PullPushAdapter(channel, this, this);
            channel.getState(null, 5000);
        }
        catch(Exception e) {
            System.err.println(e.toString());
        }
        
	}
	

    public void receive(Message msg) {
        Object o;
    	byte[] buff;

        try {

        	buff = msg.getBuffer();
        	Tool t = (Tool) Util.objectFromByteBuffer(buff);
        	c.frame.canvas.drawObject(t);
        }
        catch(Exception e) {
            System.out.println("Comm.receive(): " + e);
        }
    }
    
    public byte[] getState(String state_id) {
		return null;
	}
    
    public byte[] getState() {
        try {
            return Util.objectToByteBuffer(null);
        }
        catch(Exception e) {
            return null;
        }
    }

    public void setState(byte[] state) {
        try {
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public void setState(String state_id, byte[] state) {
	}
    
    public void getState(OutputStream os) {
    	ObjectOutputStream oos =null;
		try {
			oos = new ObjectOutputStream(os);			
	    	oos.flush();
		} catch (IOException e) {}  
		finally
		{
			try {				
				oos.close();
			} catch (IOException e) {
				System.err.println(e);
			}
		}
    }
    
    public void setState(InputStream is) {
    	ObjectInputStream ois = null;
		try {			
			ois = new ObjectInputStream(is);
		} catch (Exception e) {} 
		finally
		{
			try {				
				ois.close();
			} catch (IOException e) {
				System.err.println(e);
			}
		}
    }
    
    public void getState(String state_id, OutputStream ostream) {		
	}

	public void setState(String state_id, InputStream istream) {	
	}


    public void viewAccepted(View new_view) {
        System.out.println("Received view " + new_view);
    }

    public void suspect(Address suspected_mbr) {
    }
    
    public void block() {      
    }
    
    public void unblock() {     
    }


    public synchronized void stop() {
        try {
            System.out.print("Stopping PullPushAdapter");
            ad.stop();
            System.out.println(" -- done");

            System.out.print("Disconnecting the channel");
            channel.disconnect();
            System.out.println(" -- done");

            System.out.print("Closing the channel");
            channel.close();
            System.out.println(" -- done");
            System.exit(0);
        }
        catch(Exception e) {
            e.printStackTrace();
            System.err.println("Failed leaving the group: " + e.toString());
        }
    }
    
    public void send(byte[] s) {
        try {
            Message msg=new Message(null, null, s);
            channel.send(msg);
        }
        catch(Exception e) {
            System.err.println("Failed sending message: " + e.toString());
        }
    }
       
}