import cnrg.itx.signal.*;
import cnrg.itx.signal.SignalEvent.*;
import cnrg.itx.datax.*;
import cnrg.itx.ITXException;
import cnrg.itx.datax.devices.*;
import java.util.Enumeration;
import java.io.*;
import java.net.*;

public class client extends Thread implements SignalingObserver
{
	public String username;
	public String password;
	public int port;
	public String ip;
	public DesktopSignaling ds;
	public DataInputStream in;
	public DataOutputStream out;
	public Socket sock;
	private VirtualNetworkDestination m_vnd = new VirtualNetworkDestination();
	private SignalConnection m_sigConn;
	private byte packet[] = new byte[106];
	
	public void run() {
		while(true) {
			try {
				in.read(packet);
				switch(packet[0]) {
				case proxy.CEP_DISCONNECT:
					ds.logout();
					return;
				case proxy.CEP_INVITATION:
					try {
						Channel inChannel = new Channel();
						inChannel.setSource(new VirtualNetworkSource(ip, port, 400));
						inChannel.addDestination(new NullDestination());
						Channel outChannel = new Channel();
						outChannel.setSource(new NullSource());
						outChannel.addDestination(m_vnd);
						Connection c = new AudioConnection(inChannel, outChannel);
						m_sigConn = ds.Dial(new String(packet, 6, packet[2]), inChannel, outChannel);
						packet[0] = proxy.CEP_SETPEERADDR;
						byte host[] = m_vnd.m_peer.getHostAddress().getBytes();
						packet[2] = (byte)host.length;
						for(int i = 0; i<host.length; i++) {
							packet[6+i] = host[i];
						}
						byte peerport[] = Integer.toString(m_vnd.m_port).getBytes();
						packet[4] = (byte)host.length;
						for(int i = 0; i<peerport.length; i++) {
							packet[6+80+i] = peerport[i];
						}
						try {
							out.write(packet);
						} catch (IOException ioe) {
							ds.logout();
							return;
						}
					} catch (ITXException itxe) {
					}
					break;
				case proxy.CEP_HANGUP:
					try {
						ds.Hangup(m_sigConn);
					} catch (DesktopSignalingException dse) {
					}
					break;
				default:
					break;
				}
			} catch (IOException ioe) {
				ds.logout();
				try {
					sock.close();
				} catch (IOException e) {
				}
				return;
			}
		}
	}
	
	/**
	 * This method informs the application that a peer application's invitation
	 * has been received.
	 * 
	 * @param ise is the InviteSignalEvent that contains all the information about
	 * the caller application.
	 * @return  void
	 * 
	 * @see cnrg.itx.signal.SignalEvent.InviteSignalEvent
	 */
	public void onInvite(InviteSignalEvent ise)
	{
		try {
			Channel inChannel = new Channel();
			inChannel.setSource(new VirtualNetworkSource(ip, port, 400));
			inChannel.addDestination(new NullDestination());
			Channel outChannel = new Channel();
			outChannel.setSource(new NullSource());
			outChannel.addDestination(m_vnd);
			Connection c = new AudioConnection(inChannel, outChannel);
			PropertiesCollection pc = ise.getPropertiesCollection();
			int iPort = 0;
			InetAddress iaPeer = null;
			for (Enumeration e = pc.getProperties(); e.hasMoreElements() ; )
			{
				Object prop = e.nextElement();
				
				if (prop instanceof NetworkProperty)
				{
					iPort = ((NetworkProperty)prop).getPort();
					iaPeer = ((NetworkProperty)prop).getAddress();
					break;
				}
			}
			if(iaPeer == null) {
				ise.reject("Can't find Network Property");
				return;
			}
			packet[0] = proxy.CEP_SETPEERADDR;
			byte host[] = iaPeer.getHostAddress().getBytes();
			packet[2] = (byte)host.length;
			for(int i = 0; i<host.length; i++) {
				packet[6+i] = host[i];
			}
			byte peerport[] = Integer.toString(iPort).getBytes();
			packet[4] = (byte)host.length;
			for(int i = 0; i<peerport.length; i++) {
				packet[6+80+i] = peerport[i];
			}
			try {
				out.write(packet);
			} catch (IOException ioe) {
				ds.logout();
				return;
			}
			ise.accept(c);
		} catch (Exception e) {
			ise.reject("Unknown Error");
		}
	};

	/**
	 * This method informs the application that a peer application has sent
	 * a confirmation and the call setup is complete.
	 * 
	 * @param  sc is the SignalConnection the Application should use for data exchange.
	 *         The connection within SignalConnection may be instantiated by the application.
	 * 
	 * @return  void
	 * 
	 * @see cnrg.itx.signal.client.SignalConnection
	 */
	public void onStartCall(SignalConnection sc)
	{
		m_sigConn = sc;
		try {
			sc.open();
		} catch (DataException de) {
		}
	};
	
	/**
	 * This method informs the application that it should abort the call it was
	 * waiting for.
	 * 
	 * @param ase is the AbortSignalEvent describing the reason for the abort and
	 * which indicates the user that aborted the invite and returns the connection object
	 * the onInvite call gave signaling, if any.
	 * @return  void
	 */
	public void onAbortCall(AbortSignalEvent ase)
	{
	};
	
	/**
	 * This method informs the application that a peer application has hung up.
	 * 
	 * @param hse is the HangupSignalEvent that contains all the information about
	 * the application that has hung up.
	 * @return  void
	 * 
	 * @see cnrg.itx.signal.SignalEvent.HangupSignalEvent
	 */
	public void onHangup(HangupSignalEvent hse)
	{
	};
	
	/**
	 * This method informs the application that a DTMF has been received.
	 * 
	 * @param dtmfse is the DTMFSignalEvent that contains the tone(s).
	 * @return  void
	 * 
	 * @see cnrg.itx.signal.SignalEvent.DTMFSignalEvent
	 */
	public void onDTMF(DTMFSignalEvent dtmfse)
	{
	};
}
