package com.broadsoft.clients.cap;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;

import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceException;

import org.apache.axis.AxisFault;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

public class TestWebService {
  public static String regAuth = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
      "<BroadsoftDocument protocol=\"CAP\" version=\"13.0\">" +
        "<command commandType=\"registerAuthentication\">" +
        "<commandData><user userType=\"CallClient\"><id>USERNAME</id>" +
        "<applicationId>CommPilotController</applicationId></user></commandData>" +
        "</command></BroadsoftDocument>";
    //<?xml version="1.0" encoding="UTF-8"?><BroadsoftDocument protocol="CAP" version="11.1"><command commandType="responseAuthentication"><commandData><user userType="CallClient"><id>neeraj@broadsoft.com</id><applicationId>CommPilotController</applicationId></user><nonce>1097264289071</nonce><algorithm>MD5</algorithm></commandData></command></BroadsoftDocument>

    public static String regRes = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
        "<BroadsoftDocument protocol=\"CAP\" version=\"13.0\">" +
        "<command commandType=\"registerRequest\"><commandData>" +
        "<user userType=\"CallClient\">" +
        "<id>USERNAME</id>" +
        "<securePassword>PASSWORD</securePassword>" +
        "<applicationId>CommPilotController</applicationId>" +
        "</user></commandData></command></BroadsoftDocument>";
    //<?xml version="1.0" encoding="UTF-8"?><BroadsoftDocument protocol="CAP" version="11.1"><command commandType="registerResponse"><commandData><user userType="CallClient" userUid="198078260"><id>neeraj@broadsoft.com</id><applicationId>CommPilotController</applicationId></user></commandData></command></BroadsoftDocument>
    public static String acknowledgement = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
        "<BroadsoftDocument protocol=\"CAP\" version=\"13.0\">" +
        "<command commandType=\"acknowledgement\">" +
        "<commandData><user id=\"USERNAME\" userType=\"CallClient\" userUid=\"USERUID\">" +
        "<message messageName=\"registerResponse\"/>" +
        "<applicationId>CommPilotController</applicationId></user></commandData></command></BroadsoftDocument>";

    public static String dialCommand = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
        "<BroadsoftDocument protocol=\"CAP\" version=\"13.0\">" +
        "<command commandType=\"callAction\"><commandData>" +
        "<user userType=\"CallClient\" userUid=\"USERUID\">" +
        "<action actionType=\"Dial\">" +
        "<actionParam actionParamName=\"Number\">PHONENUMBER</actionParam>" +
        "</action></user></commandData></command></BroadsoftDocument>";

    public static String unregister = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
        "<BroadsoftDocument protocol=\"CAP\" version=\"13.0\">" +
        "<command commandType=\"unRegister\">" +
        "<commandData><user userLogoutReason=\"ClientLogout\" userType=\"CallClient\" userUid=\"USERUID\">" +
        "<applicationId>CommPilotController</applicationId></user></commandData></command></BroadsoftDocument>";


  public static void main(String[] args) throws Exception {
    //BWServiceLogger.initialize("C:/Temp");
    if( args.length<4 ){
      //Show help
      return;
    }

    String whichService = args[0];

    String name = args[1];
    String password = args[2];
    String number = args[3];
    TestWebService testWebService = new TestWebService();

    if (whichService.compareTo("-e") == 0) {
      testWebService.TestClickToDial(name, password, number);
    }
    else if(whichService.compareTo("-p") == 0) {
      //testWebService.TestProvisioningServiceTest("");
    }
  }

  private String TestExecutionServiceLogin(Call call, String userName,
                                         String password) {
    String req = regAuth;
    req = req.replaceFirst("USERNAME", userName);
    System.out.println(req);
    String response = "";
    try {
      System.out.println("\nSending Request: " + req );
      response = (String) call.invoke(new Object[] {new String(req)});
      if( response==null || response.length()==0 ){
        System.out.println("\nReceived null response");
        return "";
      }
      System.out.println("\nReceived response: " + response );

    }
    catch( AxisFault af ){
      System.out.println(af);
      return "";
    }
    catch (RemoteException ex) {
      System.out.println(ex);
      return "";
    }

    //Strip out the nonce key
    int pos1 = response.lastIndexOf("<nonce>");
    int pos2 = response.lastIndexOf("</nonce>");
    String nonce = response.substring(pos1, pos2);
    nonce = nonce.replaceFirst("<nonce>", "");
    nonce.trim();
    System.out.println(nonce);

    //Get the secure password
    String hashPassword = TestClientUtil.shaMessageDigest(password);
    if (hashPassword == null) {
      return "";
    }
    String passwordDigest = TestClientUtil.md5MessageDigest(nonce + ":" +
        hashPassword);
    if (passwordDigest == null) {
      return "";
    }

    req = regRes.replaceFirst("USERNAME", userName);
    req = req.replaceFirst("PASSWORD", passwordDigest);
    try {
      System.out.println("\nSending Request: " + req );
      response = (String) call.invoke(new Object[] {new String(req)});
      System.out.println("\nReceived response: " + response );
    }
    catch( AxisFault af ){
      System.out.println(af);
      return "";
    }
    catch (RemoteException ex) {
      System.out.println(ex);
      return "";
    }

    String userUID = "";
    try {
      MessageParser msgPar = new MessageParser(); 
      msgPar.parse(response);
      userUID = msgPar.getUserUID();
      if( userUID==null || userUID.length()==0 ){
        System.out.println("\nDid not receive userUID. Command has failed: " + response );
        return  "";
      }
    }
    catch (IOException ex1) {
      return "";
    }
    catch (SAXException ex1) {
      return "";
    }
    catch (Exception ex1) {
      return "";
    }

    req = acknowledgement.replaceFirst("USERNAME", userName);
    req = req.replaceFirst("USERUID", userUID );
    try {
      System.out.println("\nSending Request: " + req );
      response = (String) call.invoke(new Object[] {new String(req)});
      System.out.println("\nReceived response: " + response );
    }
    catch( AxisFault af ){
      System.out.println(af);
      return "";
    }
    catch (RemoteException ex) {
      System.out.println(ex);
      return "";
    }

    return userUID;
  }

  private void TestDial( Call call, String userUID, String phonenumber ){
    String req = "";
    req = dialCommand.replaceFirst("USERUID", userUID);
    req = req.replaceFirst("PHONENUMBER", phonenumber);
    String response = "";
    try {
      System.out.println("\nDialing number: " + phonenumber );
      response = (String) call.invoke(new Object[] {new String(req)});
    }
    catch( AxisFault af ){
      System.out.println(af);
      System.out.println( af.getFaultReason() );

      System.out.println(af.getFaultActor());

      if( af.getFaultDetails().length > 0 ){
        Node node = af.getFaultDetails()[0];
        int num = node.getChildNodes().getLength();
        if (num > 0) {
          String temp = node.getFirstChild().getNodeValue();
          System.out.println(temp);
        }
      }
      return;
    }
    catch (RemoteException ex) {
      System.out.println(ex);
      return;
    }
    System.out.println("Successfully dialed the number");
  }

  private void TestLogoff(Call call, String userUID) {

    String req = "";
    req = unregister.replaceFirst("USERUID", userUID);
    String response = "";
    try {
      System.out.println("\nLogging off");
      response = (String) call.invoke(new Object[] {new String(req)});
    }
    catch (AxisFault af) {
      System.out.println(af);
      System.out.println(af.getFaultReason());
      System.out.println(af.getFaultActor());
      Node node = af.getFaultDetails()[0];
      int num = node.getChildNodes().getLength();
      if (num > 0) {
        String temp = node.getFirstChild().getNodeValue();
      }
    }
    catch( RemoteException rex ){
      System.out.println( rex );
    }
  }

  private void TestClickToDial( String userName, String password, String phonenumber ){
    //Create the call object
    try {
      Service service = new Service();
      service.setMaintainSession(true);

      Call call = (Call) service.createCall();
      call.setMaintainSession(true);
      Integer timeout = new Integer(30000);

      String endpoint = "http://localhost/webservice/services/ExecutionService";
      call.setTargetEndpointAddress(new URL(endpoint));
      call.setOperationName(new QName("processMessage"));

      //System.out.println("\n*********************************************");
      //System.out.println("Test dial before login");
      //TestDial( call, "1234356", phonenumber);

      String userUID  = "";
      /*System.out.println("*********************************************");
      System.out.println("Test login to execution service with wrong password");
      userUID = TestExecutionServiceLogin(call,userName, "Wrongpassword");
      if( userUID==null || userUID.length()==0 ){
        System.out.println("FAILED");
      }else{
          System.out.println("SUCCEEDED");
      }
      */

      System.out.println("\n*********************************************");
      System.out.println("Test login to execution service with wrong user name");
      userUID = TestExecutionServiceLogin(call, "WrongUsername", password);
      if (userUID == null || userUID.length() == 0) {
        System.out.println("FAILED");
      }
      else {
        System.out.println("SUCCEEDED");
      }

      System.out.println("\n*********************************************");
      System.out.println("Test login to execution service with correct user name and password");
      userUID = TestExecutionServiceLogin(call,userName,password);
      if( userUID==null || userUID.length()==0 ){
        System.out.println("FAILED");
      }else{
          System.out.println("SUCCEEDED");
      }

      //

      //Now the login is done. Now make a call.
      System.out.println("\n*********************************************");
      System.out.println("Test Dial with WRONG UserUID");
      TestDial( call, "123456", phonenumber);


      System.out.println("\n*********************************************");
      System.out.println("Test Dial with RIGHT UserUID");
      TestDial( call, userUID, phonenumber);

      //Logging off.
      System.out.println("\n*********************************************");
      System.out.println("Test logoff");
      TestLogoff(call, userUID);

    //Now the login is done. Now make a call.
    System.out.println("\n*********************************************");
    System.out.println("Test dial after logoff");
    TestDial( call, userUID, phonenumber);

      /*while( true ){
        System.out.println(
            "Type the number to dial and press return or Press return to exit");
        BufferedReader stdinIO = new BufferedReader(new InputStreamReader(
            System.in));

        try {
          phonenumber = stdinIO.readLine();
        }
        catch (IOException ex2) {
          System.out.println("Error occured while reading console input. Exiting the application");
          System.exit(0);
        }

        if( phonenumber.length()==0 ){
          System.out.println("Bye");
          return;
        }

        req = dialCommand.replaceFirst("USERUID", userUID);
        req = req.replaceFirst("PHONENUMBER", phonenumber);

        response = (String) call.invoke(new Object[] {new String(req)});

      }*/


    }
    catch (MalformedURLException ex) {
    }
    catch (ServiceException ex) {
    }
  }

  private void TestProvisioningServiceLogin( Call call, String userName, String password ){

  }

  private void TestProvisioningServiceTest( String userName, String password  ) {

    try {
      Service service = new Service();
      service.setMaintainSession(true);

      Call call = (Call) service.createCall();
      call.setMaintainSession(true);
      Integer timeout = new Integer(30000);

      //call.setTimeout(timeout);
      String endpoint = "http://localhost/webservice/services/ProvisioningService";
      call.setTargetEndpointAddress(new URL(endpoint));
      call.setOperationName(new QName("processMessage"));

      TestProvisioningServiceLogin( call, userName, password );

      String position = "";
      int i = 0;
      while (position == "") {
        try {
          i++;
          System.out.println("Sending " + i);
          position = (String) call.invoke(new Object[] {new String("")});
          Thread.currentThread().sleep(100);
        }
        catch (AxisFault af) {
          System.err.println("Exception Description " + af.getFaultReason());
          continue;
        }

        //System.out.println("Got result : " + position);
        if (position == null || position.length() == 0){
          System.out.println("Did not get response");
        }
        else{
          System.out.println("Got result : " + position);
        }
        position = "";
      }

    }

    catch (AxisFault af) {
      System.err.println("Exception Description " + af.getFaultReason());
    }
    catch (Exception e) {
      System.err.println("Exception Description " + e);
      System.err.println("Exception Description " + e.getMessage());

    }
  }
}
