/*
 * Created on Aug 11, 2005
 *  
 */
package com.broadsoft.clients.oci.ocs;

import java.io.*;
import java.net.Socket;
import java.net.SocketException;

public class OCSClient
{
  private Socket       m_socket;
  private InputStream  m_inStream;
  private OutputStream m_outStream;
  private String       m_inMsg;
  private Receiver     m_receiver;
  private Object       m_waitObj = new Object();
  
  public OCSClient()
  {
  }
  
  public void connect (String host, int port) throws Exception
  {
    try
    {
      // Create the socket to the server
      m_socket = new Socket(host, port);
      m_inStream  = m_socket.getInputStream();
      m_outStream = m_socket.getOutputStream();
      m_receiver = new Receiver(m_inStream);
      m_receiver.start();   
    }
    catch(java.net.NoRouteToHostException e)
    {
      System.out.println(e.getMessage() + "\nValidate that the address " +
                         host+ " and port " + port + 
                         " are valid and the remote host is up and running");
      m_socket=null;
      throw new Exception(e);
    }
    catch(java.net.ConnectException e)
    {
      System.out.println(e.getMessage() + "\nValidate that the address " +
                         host + " and port " + port +
                         " are valid and the remote host is up and running");
      m_socket = null;
      throw new Exception(e);
    }
    catch(Exception e)
    {
      System.out.println("Exception: " + e.getMessage());
      e.printStackTrace();
      m_receiver.stop();
      m_socket.close();
      m_socket = null;
      throw new Exception(e);
    }
  }
  
  public void disconnect() throws Exception
  {
    m_receiver.stop();
    m_socket.close();
  }
  
  public boolean isClosed()
  {
    return m_socket.isClosed();
  }
  
  public String sendMessage(String message, int timeout) throws Exception
  {
    String reply = sendWaitReply(message, timeout);
        
    return reply;
  }
  
  private String sendWaitReply(String message, int timeout) throws Exception
  {
    m_inMsg = null;
    try
    {
      m_outStream.write(message.getBytes());
    }
    catch (IOException e)
    {
      throw new Exception("Failed to write packet: ", e);
    }
    synchronized(m_waitObj)
    {
      if (timeout < 0)
      {
        m_waitObj.wait();
      }
      else
      {
        m_waitObj.wait(timeout*1000);
      }
    }
    
    return m_inMsg;
  }
  
  private void handleIncomingMessage(String packet)
  {
    // Incoming message, deliver it
    m_inMsg = packet;
    synchronized(m_waitObj)
    {
      m_waitObj.notify();
    }
  }
  
  private class Receiver implements Runnable
  {
    private boolean     m_run = false;
    private Thread      m_thread;
    private BufferedReader m_inStream;
    
    public Receiver(InputStream inStream)
    {
      m_inStream = new BufferedReader(new InputStreamReader(inStream));
    }
    
    public void start()
    {
      m_run    = true;
      m_thread = new Thread(this, "OCSReceiver");
      m_thread.start();
    }
    
    public void stop()
    {
      m_run = false;
    }
    
    public void run() 
    {
      String line;
      String BSOFT_END_TAG = "</BroadsoftDocument>";

      while (m_run)
      {
        StringBuffer message = new StringBuffer();
        try
        {
          do
          {
            line = m_inStream.readLine();
            message.append(line);
          } while(!line.contains(BSOFT_END_TAG));
          
          handleIncomingMessage(message.toString());
        }
        catch (SocketException e)
        {
          if (m_run)
            System.out.println("Failed to read, socket exception: " + e.getMessage());
          return;
        }
        catch (IOException e)
        {
          System.out.println("Failed to read, IO exception: " + e.getMessage());
          return;
        }
        catch (Exception e)
        {
          System.out.println("Failed to read, exception: " + e.getMessage());
          return;
        }
      }
    }
  } 
}
