#include "client.h"

int Client::transferCall (OSRTSocket& cstaSocket)
{
   /*
   My read of the CSTA documentation is such that a call transfer involves
   first sending a Consultation Call message followed by a Transfer Call
   message.  But CSTA's definition of a call transfer isn't intuitive.  In
   CSTA parlance a call transfer is a transfer of a call from a held state
   to an active state at the same device.

   This results in the following scenario:

   1.  A Make Call is done to initiate a call from 103 to 102.
   2.  A Transfer Call is done to transfer the call to 101.
   3.  As part of the transfer call processing, a Consultation Call
       message is sent that puts the call from 103 to 102 on hold
       and causes 101 to ring.
   4.  The second part of the transfer call processing is sending
       a Transfer Call message.  This causes the call to be a
       call from 102 to 101; 103 is now out of the picture.
   
   To me if 103 calls 102, and the call is to be transferred to 101,
   the end result should be a call from 103 to 101, not 102 to 101.
   It appears that a call from 103 to 101 is what happens after the
   Consultation Call message.  101 can pick up and seems to have a
   call from 103; 102 at this point can just hang up, and the call
   from 103 to 101 remains active.

   So perhaps the sending of the Transfer Call message isn't really
   necessary?  It's commented out below.
   */
   OSOCTET	msgbuf[MAXMSGLEN];
   int len;

   if (trace) {
      printf ("transfer Call \n" );
   }

   /* Initialize the encoding context */
   ASN1BEREncodeBuffer encodeBuffer (msgbuf, sizeof(msgbuf));

   /* Encode consultation call argument */
   if ((len = encodeConsCallRequest(encodeBuffer)) < 0) { return len; }

   /* Encode ROSE header on top of encoded argument */
   if ((len = encodeROSERequestHeader (encodeBuffer, len, consultationCall_CODE)) < 0) { return len; }

   /* Write the encoded message out to the socket */
   sendMessage (cstaSocket, encodeBuffer, len);
   if (trace) {
      printf ("consultation Call msg sent, len = %d \n", len);
   }

   int stat = receiveCSTAMessage (cstaSocket);	
   if (stat != 0) {
      printf ("recvMessage failed, %d \n", stat );
      return stat;
   }

   // See note at the beginning of this method for an explanation of why this
   // code is commented out.
   ///* Encode operation argument */
   //encodeBuffer.init();
   //if ((len = encodeTransferCallRequest(encodeBuffer, mInitiatedTransfer)) < 0) { return len; }

   ///* Encode ROSE header on top of encoded argument */
   //if ((len = encodeROSERequestHeader (encodeBuffer, len, transferCall_CODE)) < 0) { return len; }

   //msgptr = encodeBuffer.getMsgPtr();

   ///* Write the encoded message out to the socket */
   //sendMessage (cstaSocket, encodeBuffer, len);
   //if (trace) {
   //   printf ("transfer Call msg sent, len = %d \n", len);
   //}

   //stat = receiveCSTAMessage (cstaSocket);	
   //if (stat != 0) {
   //   printf ("recvMessage failed, %d \n", stat );
   //   return stat;
   //}

   return 0;
}

int Client::encodeTransferCallRequest(ASN1BEREncodeBuffer &encodeBuffer, 
                                      ASN1T_ConnectionID initiatedTransfer)
{
   ASN1T_TransferCallArgument transferCallArgument;
   ASN1C_TransferCallArgument transferCallArgumentC (encodeBuffer, transferCallArgument);
   int len;

   /* This is the id of the call that was originally made with MakeCall.  */
   transferCallArgument.heldCall = mMostRecentCall;

   /* This is the id that was in the response to the ConsultationCall message.  */
   transferCallArgument.activeCall = mInitiatedTransfer;

   /* Encode */

   len = transferCallArgumentC.Encode();

   if (len < 0) {
      printf ("Encode of transferCallArgument failed.\n");
      encodeBuffer.printErrorInfo();
   }

   return len;

}

int Client::encodeTransferCallRequest (ASN1BEREncodeBuffer& encodeBuffer)
{
   ASN1T_TransferCallArgument transferCallArgument;
   ASN1C_TransferCallArgument transferCallArgumentC (encodeBuffer, transferCallArgument);
   int len;

   char heldDev[MAX_NUM_SIZE];
   char connDev[MAX_NUM_SIZE];

   getstring((char *)"Held device :", heldDev, sizeof(heldDev));
   getstring((char *)"Connected device :", connDev, sizeof(connDev));
   if (trace) {
	   printf ( "encode transfer Call Request, held %s, conn %s \n", heldDev, connDev );
   }

   /* To make it simple, we will omit all of the optional fields */
   transferCallArgument.m.extensionsPresent = 0;

   ASN1T_DeviceID fromStaticID;
   char fromDev[MAX_NUM_SIZE];
   getstring((char *)"Held device no:", fromDev, sizeof(fromDev));
   fromStaticID.deviceIdentifier.t = T_DeviceID_deviceIdentifier_dialingNumber;
   fromStaticID.deviceIdentifier.u.dialingNumber = fromDev;
   ASN1T_ConnectionID_both fromBothId;
   char callid[MAX_NUM_SIZE];
   getstring((char *)"Held device call id:", callid, sizeof(callid));
   fromBothId.callID = callid;
   fromBothId.deviceID.t = T_LocalDeviceID_staticID;
   fromBothId.deviceID.u.staticID = &fromStaticID;
   transferCallArgument.heldCall.t = T_ConnectionID_both;
   transferCallArgument.heldCall.u.both = &fromBothId;;

   ASN1T_DeviceID toStaticID;
   char toDev[MAX_NUM_SIZE];
   getstring((char *)"Active device no:", toDev, sizeof(toDev));
   toStaticID.deviceIdentifier.t = T_DeviceID_deviceIdentifier_dialingNumber;
   toStaticID.deviceIdentifier.u.dialingNumber = toDev;
   ASN1T_ConnectionID_both toBothId;
   char toCallid[MAX_NUM_SIZE];
   getstring((char *)"Active device call id:", toCallid, sizeof(toCallid));
   toBothId.callID = toCallid;
   toBothId.deviceID.t = T_LocalDeviceID_staticID;
   toBothId.deviceID.u.staticID = &toStaticID;
   transferCallArgument.activeCall.t = T_ConnectionID_both;
   transferCallArgument.activeCall.u.both = &toBothId;;

   /* Encode */

   len = transferCallArgumentC.Encode();

   if (len < 0) {
      printf ("Encode of transferCallArgument failed.\n");
      encodeBuffer.printErrorInfo();
   }

   return len;
}

void Client::processTransferCallRes(ASN1T_TransferCallResult& transferCallRes)
{
   printf ("Transfer Call completed successfully\n");
   printf ("Transfer Call info:\n");

   asn1Print_ConnectionID (
      "TransferredCallResult", &transferCallRes.transferredCall);

}

int Client::encodeConsCallRequest(ASN1BEREncodeBuffer &encodeBuffer)
{
   if (!callInitiated)
   {
      printf ("Make a call first with MakeCall.\n");
      return -1;
   }

   ASN1T_ConsultationCallArgument consCallArgument;
   ASN1C_ConsultationCallArgument consCallArgumentC (encodeBuffer, consCallArgument);
   int len;

   char targetDev[MAX_NUM_SIZE];

   getstring((char *)"Target device :", targetDev, sizeof(targetDev));

   if (trace) {
	   printf ( "encode consultation Call Request, target %s \n", targetDev );
   }

   consCallArgument.existingCall = mMostRecentCall;
   consCallArgument.consultedDevice.deviceIdentifier.t = T_DeviceID_deviceIdentifier_dialingNumber;
   consCallArgument.consultedDevice.deviceIdentifier.u.dialingNumber = targetDev;
   consCallArgument.consultOptions = ConsultOptions::transferOnly;

   /* Encode */

   len = consCallArgumentC.Encode();

   if (len < 0) {
      printf ("Encode of consultationCallArgument failed.\n");
      encodeBuffer.printErrorInfo();
   }

   return len;
}

void Client::processConsCallRes(ASN1T_ConsultationCallResult& consCallRes)
{
   mInitiatedTransfer = consCallRes.initiatedCall;
}
