package wbModule;
import utility.*;
import java.awt.*;
import java.util.Hashtable;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.io.*;
import java.net.*;
public class WbClientHandler extends ClientHandler
{
	AgentIdentity id ;
	public Gui g = null;
	public PointSender ptS = null;
	Component whiteboard;
	boolean loggedIn = false;
	protected EventListenerList changeListeners = new EventListenerList() ;

	public WbClientHandler()
	{

		g =new Gui();
		ptS = new PointSender(this);
	}
	public WbClientHandler(InputStream in, OutputStream out)
	{
		super(in,out);
		g =new Gui();
		ptS = new PointSender(this);
	}


	public void doThis(Response res)
	{


		if (loggedIn)
		{
			if( res.getResponseType().compareTo("StartPoint") == 0)
			{

				WbPoint pt = (WbPoint)res.getObject();
				String logName = pt.id.getLoginName();
				if(logName.compareTo(this.id.getLoginName()) != 0)
				{

					synchronized(g.lastPt)
					{
						g.lastPt.put(logName,pt.pt);
 					}
				}

			}
			else if( res.getResponseType().compareTo("EndPoint") == 0)
			{

				WbPoint pt = (WbPoint)res.getObject();
				String logName = pt.id.getLoginName();
				if(logName.compareTo(this.id.getLoginName()) != 0)
				{

					Graphics gr=whiteboard.getGraphics();
					Point lp ;
					synchronized(g.lastPt)
					{
						lp = (Point)g.lastPt.get(logName);
					}
      					gr.drawLine(lp.x, lp.y, pt.pt.x, pt.pt.y);

					synchronized(g.lastPt)
					{
						g.lastPt.remove(logName);

					}
				}
			}
			else if( res.getResponseType().compareTo("DragPoint") == 0)
			{

				WbPoint pt = (WbPoint)res.getObject();
				String logName = pt.id.getLoginName();
				if(logName.compareTo(this.id.getLoginName()) != 0)
				{

	    				Graphics gr=whiteboard.getGraphics();
					Point lp ;
					synchronized(g.lastPt)
					{
						 lp = (Point)g.lastPt.get(logName);
					}
					gr.drawLine(lp.x, lp.y, pt.pt.x, pt.pt.y);
      					synchronized (g.lastPt)
					{
							g.lastPt.put(logName,pt.pt);
  					}

				}
			}
			else
				System.out.println("in doThis method: Unknown response"+res.getResponseType());
		}

	}
	public void setAgentId (AgentIdentity id)
	{
		this.id = id;
	}

	public class Gui   extends JInternalFrame implements Runnable
	{

		Hashtable lastPt = new Hashtable();
		Frame  frameContainer;
		public Thread t ;

		public Gui()
		{
			super("Shared White Board",false,true,false,true);
			t= new Thread(this);
			t.run();
		}

		public void run()
		{
			buildGUI();
			setupEventHandlers();
			//loggedIn = true;
		}
		public void showGui()
		{
			loggedIn = true;
			setVisible(true);
		}

		void buildGUI()
		{
			frameContainer = new Frame();
			GridBagLayout gridbag = new GridBagLayout();
    			GridBagConstraints c = new GridBagConstraints();
    			frameContainer.setLayout(gridbag);
        		c.fill = GridBagConstraints.BOTH;
    			c.gridwidth = GridBagConstraints.REMAINDER;
    			Canvas canvas1 = new Canvas();
			canvas1.setBackground(Color.white);
    			gridbag.setConstraints(canvas1, c);
    			frameContainer.add(canvas1);
	    		whiteboard = canvas1;
    			frameContainer.setVisible(false);
			//System.out.println("it sucks");
			getContentPane().add(whiteboard);
			setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
		}

		void setupEventHandlers()
		{

			whiteboard.addMouseListener(new WbMouseListener());
			whiteboard.addMouseMotionListener(new WbMouseMotionListener());
			addInternalFrameListener(new WindowHandler());
		}

		public class WbMouseListener extends MouseAdapter
		{
			public void mousePressed(MouseEvent ev)
			{
				//System.out.println("working mouse pressed");
				String logName = id.getLoginName();
				Point evPt = ev.getPoint();
    				ptS.addHeader(new WbPoint(id,evPt),"StartPoint");
				synchronized(lastPt)
				{
					lastPt.put(logName,evPt);
 				}

 			}

			public void mouseReleased(MouseEvent ev)
			{
				//System.out.println("working mouse released");
				String logName = id.getLoginName();

				Graphics gr=whiteboard.getGraphics();
				Point evPt = ev.getPoint();
    				Point currPt = evPt;
      				ptS.addHeader(new WbPoint(id,evPt),"EndPoint");
				Point lp;
				synchronized (lastPt)
				{
					 lp = (Point)lastPt.get(logName);
				}
				gr.drawLine(lp.x, lp.y, currPt.x, currPt.y);

				synchronized(lastPt)
				{
					lastPt.remove(logName);
  				}
			}

		}

  		public class WbMouseMotionListener extends MouseMotionAdapter
		{


  			public void mouseDragged(MouseEvent ev)
			{
  				//System.out.println("working mouse draged");
				String logName = id.getLoginName();

    				Graphics gr=whiteboard.getGraphics();
				Point evPt = ev.getPoint();
    				ptS.addHeader(new WbPoint(id,evPt),"DragPoint");
				Point currPt = evPt;
    				Point lp ;
				synchronized(lastPt)
				{
					 lp = (Point)lastPt.get(logName);
				}

      				gr.drawLine(lp.x, lp.y, currPt.x, currPt.y);
      				synchronized (lastPt)
				{
					lastPt.put(logName,currPt);
  				}

  			}




		}
		public class WindowHandler extends InternalFrameAdapter
		{
			public void internalFrameClosed(InternalFrameEvent e)
			{
				fireChange();
				RemoveConnection rmc = new RemoveConnection(id);
				Request req = new Request(rmc,"RemoveConnection");
				ClientHeader toBeSent = new ClientHeader(req);
				try
				{
					sendRequest(toBeSent);
				}
				catch(Exception ex)
				{
					ex.printStackTrace();
				}
				removeConnection();

			}
		}

		public void addChangeListener(ChangeListener x)
		{
			changeListeners.add (ChangeListener.class, x);

		}
		public void removeChangeListener(ChangeListener x)
		{
			changeListeners.remove (ChangeListener.class, x);
		}
		protected void fireChange()
		{

			ChangeEvent c = new ChangeEvent(this);

			Object[] listeners = changeListeners.getListenerList();

			for (int i = listeners.length-2; i >= 0; i -= 2)
			{
				if (listeners[i] == ChangeListener.class)
				{
					ChangeListener cl = (ChangeListener)listeners[i+1];
					cl.stateChanged(c);
				}
			}
		}

	}
}

