github.com/grokify/go-ringcentral-client@v0.3.31/engagevoice/v1/js/cf-agent-library_v2.1.16-2019-07-09.js (about)

     1  /*! cf-agent-library - v2.1.16 - 2019-07-09 */
     2  /**
     3   * @fileOverview Exposed functionality for Contact Center AgentUI.
     4   * @version 2.1.8
     5   * @namespace AgentLibrary
     6   */
     7  ;(function (global) {
     8  var AddSessionNotification = function() {
     9  };
    10  /*
    11   * This class is responsible for handling "ADD-SESSION" packets from IntelliQueue.  This is used by
    12   * the CallControlForm. Then it will increment the total_calls count.
    13   *
    14   * {
    15   *   "ui_notification": {
    16   *       "@message_id": "IQ982008082918151403727",
    17   *       "@response_to": "",
    18   *       "@type": "ADD-SESSION",
    19   *       "session_id": { "#text": "2" },
    20   *       "uii": { "#text": "200808291814560000000900016558" },
    21   *       "phone": { "#text": "200808291814370000000900016555" },
    22   *       "session_type": { "#text": "AGENT" },
    23   *       "session_label": { "#text": "Primary Agents Call Session" },
    24   *       "allow_control": { "#text": "TRUE" },
    25   *       "monitoring": { "#text": "FALSE" },
    26   *       "agent_id": { "#text": "1856" }
    27   *   }
    28   *  }
    29   */
    30  AddSessionNotification.prototype.processResponse = function(notification) {
    31      var formattedResponse = utils.buildDefaultResponse(notification);
    32      var model = UIModel.getInstance();
    33      var notif = notification.ui_notification;
    34      var sessionAgentId = utils.getText(notif, "agent_id");
    35      if(utils.getText(notif, "session_type") === "AGENT"){
    36          model.incrementTotalCalls();
    37      }
    38      if(sessionAgentId === model.agentSettings.agentId){
    39          // add the session_id of this leg to the current call packet -
    40          // this way we can use it for hangups later.
    41          model.currentCall.sessionId = utils.getText(notif, "session_id");
    42      }else if(sessionAgentId != ""){
    43          // this is a monitoring session, lets save the monitored agent id for barge-ins
    44          model.currentCall.monitorAgentId = sessionAgentId;
    45      }
    46      // Check to see if we have a transfer leg here, if so, register it
    47      var sessionType = utils.getText(notif, "session_type"),
    48          allowControl = utils.getText(notif, "allow_control"),
    49          sessionId = utils.getText(notif, "session_id"),
    50          uii = utils.getText(notif, "uii"),
    51          isMonitoring = model.currentCall.isMonitoring,
    52          monitoringType = model.currentCall.monitoringType;
    53      var isBargeInMonitor = isMonitoring && monitoringType === 'FULL',
    54          notCurrentAgent = sessionAgentId !== model.agentSettings.agentId,
    55          notSessionOne = sessionId !== '1',
    56          shouldTrackSession = false;
    57      if(notSessionOne && notCurrentAgent) {
    58          if(isBargeInMonitor) {
    59              shouldTrackSession = true;
    60          } else if(allowControl) {
    61              if(sessionType === 'OUTBOUND' || sessionType === 'AGENT') {
    62                  shouldTrackSession = true;
    63              }
    64          }
    65      }
    66      if(shouldTrackSession) {
    67          var destination = utils.getText(notif, "phone");
    68          if(sessionType === 'AGENT' || sessionAgentId !== '') {
    69              destination = utils.getText(notif, "agent_name");
    70          }
    71          model.transferSessions[sessionId] = {
    72              sessionId: sessionId,
    73              destination: destination,
    74              uii: uii
    75          };
    76      }
    77      // if agent session, set on call status
    78      if(notif.session_id === '2'){
    79          model.agentSettings.onCall = true;
    80      }
    81      formattedResponse.status = "OK";
    82      formattedResponse.message = "Received ADD-SESSION notification";
    83      formattedResponse.sessionId = utils.getText(notif, "session_id");
    84      formattedResponse.uii = utils.getText(notif, "uii");
    85      formattedResponse.phone = utils.getText(notif, "phone");
    86      formattedResponse.sessionType = utils.getText(notif, "session_type");
    87      formattedResponse.sessionLabel = utils.getText(notif, "session_label");
    88      formattedResponse.allowControl = utils.getText(notif, "allow_control");
    89      formattedResponse.monitoring = utils.getText(notif, "monitoring");
    90      formattedResponse.agentId = utils.getText(notif, "agent_id");
    91      formattedResponse.transferSessions = model.transferSessions;
    92      return formattedResponse;
    93  };
    94  var AdminDebugEmailNotification = function() {
    95  };
    96  /*
    97   * This class is responsible for handling "AGENT-DEBUG-EMAIL" packets from IntelliQueue
    98   *
    99   * {
   100   *   "ui_notification":{
   101   *      "@message_id":"IQD01DEV2018071616521500004",
   102   *      "@response_to":"",
   103   *      "@type":"AGENT-DEBUG-EMAIL",
   104   *      "email_to": {
   105   *          "#text":"rmyers@connectfirst.com"
   106   *      }
   107   *      "requested_by": {
   108   *          "#text":"Ross Myers"
   109   *      }
   110   *   }
   111   * }
   112   */
   113  AdminDebugEmailNotification.prototype.processResponse = function(notification) {
   114      var formattedResponse = utils.buildDefaultResponse(notification);
   115      var notif = notification.ui_notification;
   116      formattedResponse.status = "OK";
   117      formattedResponse.message = "Received AGENT-DEBUG-EMAIL notification";
   118      formattedResponse.emailTo = utils.getText(notif, "email_to");
   119      formattedResponse.requestedBy = utils.getText(notif, "requested_by");
   120      return formattedResponse;
   121  };
   122  var DialGroupChangeNotification = function() {
   123  };
   124  /*
   125   * This class is responsible for handling a DIAL_GROUP_CHANGE notification.
   126   * This event is sent from IQ when an agent's dial group is changed in through the AdminUI.
   127   *
   128   *   {
   129   *       "ui_notification": {
   130   *           "@message_id": "IQ10012016080413085500263",
   131   *           "@type": "DIAL_GROUP_CHANGE",
   132   *           "agent_id": { "#text": "1180958" },
   133   *           "dial_group_id": { "#text": "50354" },
   134   *           "dialGroupName": { "#text": "Preview Dial Mode" },
   135   *           "dial_group_desc": {}
   136   *       }
   137   *   }
   138   */
   139  DialGroupChangeNotification.prototype.processResponse = function(notification) {
   140      //Modify configRequest with new DialGroupId
   141      var model = UIModel.getInstance();
   142      var notif = notification.ui_notification;
   143      var origLoginType = model.configRequest.loginType;
   144      var newDgId = utils.getText(notif, "dial_group_id");
   145      model.dialGroupChangeNotification = notification;
   146      // Calculate type of login - called from AdminUI when assigning agent to new dial group.
   147      // Only options should be BLENDED or OUTBOUND here.
   148      if(newDgId && newDgId !== "" && (origLoginType === "INBOUND" || origLoginType === "BLENDED") ){
   149          model.configRequest.loginType = "BLENDED";
   150      }else if (newDgId && newDgId !== ""){
   151          model.configRequest.loginType = "OUTBOUND";
   152      }else if (origLoginType  === "INBOUND"){
   153          model.configRequest.loginType = "INBOUND";
   154      }else{
   155          model.configRequest.loginType = "NO-SELECTION";
   156      }
   157      UIModel.getInstance().configRequest.dialGroupId = newDgId;
   158      var formattedResponse = {
   159          message: "Dial Group Updated Successfully.",
   160          detail: "Dial Group changed to [" + newDgId + "].",
   161          dialGroupId: utils.getText(notif, "dial_group_id"),
   162          dialGroupName: utils.getText(notif, "dialGroupName"), // camel case from server for some reason :/
   163          dialGroupDesc: utils.getText(notif, "dial_group_desc"),
   164          agentId: utils.getText(notif, "agent_id")
   165      };
   166      return formattedResponse;
   167  };
   168  var DialGroupChangePendingNotification = function() {
   169  };
   170  /*
   171   * This class is responsible for handling a DIAL_GROUP_CHANGE_PENDING notification.
   172   * This event is sent from IQ when an agent's dial group is changed and the agent is on a call.
   173   *
   174   * {
   175   *     "ui_notification": {
   176   *         "@message_id": "IQ10012016080515294800318",
   177   *         "@type": "DIAL_GROUP_CHANGE_PENDING",
   178   *         "agent_id": { "#text": "1180958" },
   179   *         "dial_group_id": { "#text": "50354" },
   180   *         "update_from_adminui": { "#text": "TRUE" }
   181   *     }
   182   * }
   183   */
   184  DialGroupChangePendingNotification.prototype.processResponse = function(notification) {
   185      var model = UIModel.getInstance();
   186      var notif = notification.ui_notification;
   187      model.agentSettings.pendingDialGroupChange = parseInt(utils.getText(notif, "dial_group_id"), 10);
   188      // check if request originated with AdminUI
   189      if(notif.update_from_adminui){
   190          model.agentSettings.updateDGFromAdminUI = utils.getText(notif, "update_from_adminui") === true;
   191      }else{
   192          model.agentSettings.updateDGFromAdminUI = false;
   193      }
   194      var formattedResponse = {
   195          message: "Dial Group Change Pending notification received.",
   196          detail: "DialGroup switch for existing session pending until active call ends.",
   197          agentId: utils.getText(notif, "agent_id"),
   198          dialGroupId: utils.getText(notif, "dial_group_id"),
   199          updateFromAdminUI: utils.getText(notif, "update_from_adminui")
   200      };
   201      return formattedResponse;
   202  };
   203  var DirectAgentTransferNotification = function() {
   204  };
   205  /*
   206   * This class is responsible for handling a DIRECT-AGENT-ROUTE notification.
   207   * This event is sent from IQ when an agent is presented a direct transfer, in the case they are not in an
   208   * available state to automatically be presented the call.
   209   *
   210   * {
   211   *     "ui_notification": {
   212   *         "@message_id": "IQ10012016080515294800318",
   213   *         "@type": "DIRECT-AGENT-ROUTE",
   214   *         "response_to": { "#text": "" },
   215   *         "agent_id": { "#text": "" },
   216   *         "uii": { "#text": "" },
   217   *         "status": { "#text": "" },
   218   *         "ani": { "#text": "" },
   219   *         "dnis": { "#text": "" }
   220   *         "source_type": { "#text": "" },
   221   *         "source_id": { "#text": "" },
   222   *         "source_name": { "#text": "" }
   223   *         "voicemail_url": { "#text": "" }
   224   *     }
   225   * }
   226   */
   227  DirectAgentTransferNotification.prototype.processResponse = function(notification) {
   228      var formattedResponse = utils.buildDefaultResponse(notification);
   229      var notif = notification.ui_notification;
   230      formattedResponse.message = "Received DIRECT-AGENT-ROUTE notification";
   231      formattedResponse.status = utils.getText(notif, "status");
   232      formattedResponse.agentId = utils.getText(notif, "agent_id");
   233      formattedResponse.uii = utils.getText(notif, "uii");
   234      formattedResponse.ani = utils.getText(notif, "ani");
   235      formattedResponse.dnis = utils.getText(notif, "dnis");
   236      formattedResponse.sourceType = utils.getText(notif, "source_type");
   237      formattedResponse.sourceId = utils.getText(notif, "source_id");
   238      formattedResponse.sourceName = utils.getText(notif, "source_name");
   239      formattedResponse.voicemailUrl = utils.getText(notif, "voicemail_url");
   240      return formattedResponse;
   241  };
   242  var DropSessionNotification = function() {
   243  };
   244  /*
   245   * This class handles the DROP-SESSION packet from IQ. It doesn't really do anything
   246   * besides format a response for the callback notification since there isn't any action needed.
   247   *
   248   *  {
   249   *      "ui_notification": {
   250   *          "@message_id":"IQ10012016081613222800341",
   251   *          "@response_to":"",
   252   *          "@type":"DROP-SESSION",
   253   *          "session_id":{"#text":"3"},
   254   *          "uii":{"#text":"201608161322180139000000000124"}
   255   *      }
   256   *  }
   257   */
   258  DropSessionNotification.prototype.processResponse = function(notification) {
   259      var formattedResponse = utils.buildDefaultResponse(notification);
   260      var notif = notification.ui_notification;
   261      var sessionId = utils.getText(notif, "session_id");
   262      var transfer = UIModel.getInstance().transferSessions[sessionId];
   263      // Check to see if we just disconnected a transfer session
   264      // If so, we need to remove the session from our map
   265      if(transfer){
   266          utils.logMessage(LOG_LEVELS.DEBUG, "Transfer to " + transfer.destination + " has terminated", "");
   267          delete UIModel.getInstance().transferSessions[sessionId];
   268          formattedResponse.transferEnd = transfer;
   269      }
   270      formattedResponse.message = "Received DROP-SESSION Notification";
   271      formattedResponse.status = "OK";
   272      formattedResponse.sessionId = utils.getText(notif, "session_id");
   273      formattedResponse.uii = utils.getText(notif, "uii");
   274      return formattedResponse;
   275  };
   276  var EarlyUiiNotification = function() {
   277  };
   278  /*
   279   * This class is responsible for handling "EARLY_UII" packets from IntelliQueue.
   280   * For manual outdials, this gives the uii to cancel a ringing line.
   281   *
   282   *  {
   283   *      "ui_notification":{
   284   *          "@message_id":"IQ10012016081611595000289",
   285   *          "@type":"EARLY_UII",
   286   *          "agent_id":{"#text":"1180958"},
   287   *          "uii":{"#text":"201608161200240139000000000120"}
   288   *      }
   289   *  }
   290   */
   291  EarlyUiiNotification.prototype.processResponse = function(notification) {
   292      var formattedResponse = utils.buildDefaultResponse(notification);
   293      var notif = notification.ui_notification;
   294      formattedResponse.message = "Received EARLY_UII notification";
   295      formattedResponse.status = "OK";
   296      formattedResponse.agentId = utils.getText(notif, "agent_id");
   297      formattedResponse.uii = utils.getText(notif, "uii");
   298      return formattedResponse;
   299  };
   300  var EndCallNotification = function(libInstance) {
   301      this.libInstance = libInstance;
   302  };
   303  /*
   304   * This class is responsible for handling an END-CALL notification.
   305   * Save the packet in the UIModel by appending it to the currentCall packet.
   306   * Update the CallState field in the UIModel to "CALL-ENDED"
   307   *
   308   * {
   309   *  "ui_notification":{
   310   *      "@message_id":"IQ982008082910362203349",
   311   *      "@response_to":"",
   312   *      "@type":"END-CALL",
   313   *      "agent_id":{"#text":"1856"},
   314   *      "uii":{"#text":"200808291035510000000900029412"},
   315   *      "session_id":{"#text":"2"},
   316   *      "call_dts":{"#text":"2008-08-29 10:36:04"},
   317   *      "call_duration":{"#text":"16"},
   318   *      "term_party":{"#text":"CALLER"},
   319   *      "term_reason":{},
   320   *      "recording_url":{},
   321   *      "disposition_timeout:{"#text":"60"}
   322   *  }
   323   * }
   324   */
   325  EndCallNotification.prototype.processResponse = function(notification) {
   326      var model = UIModel.getInstance();
   327      var notif = notification.ui_notification;
   328      model.endCallNotification = notification;
   329      // add callDuration, termParty, and termReason to the current call packet
   330      model.currentCall.duration = utils.getText(notif, "call_duration");
   331      model.currentCall.termParty = utils.getText(notif, "term_party");
   332      model.currentCall.termReason = utils.getText(notif, "term_reason");
   333      // set call state to "CALL-ENDED"
   334      model.agentSettings.callState = "CALL-ENDED";
   335      model.agentSettings.onCall = false;
   336      model.agentSettings.onManualOutdial = false;
   337      // Clear out any transfer sessions from the previous call
   338      model.transferSessions = {};
   339      // Check if there is a pending dial group change
   340      if(model.agentSettings.pendingDialGroupChange > 0 || model.agentSettings.pendingDialGroupChange == -1) {
   341          // update dial group id
   342          model.configRequest.dialGroupId = model.agentSettings.pendingDialGroupChange;
   343          // send login update request
   344          this.libInstance.configureAgent(model.configRequest.queueIds, model.configRequest.chatIds, model.configRequest.skillProfileId, model.configRequest.dialGroupId, model.configRequest.dialDest, model.agentSettings.updateDGFromAdminUI);
   345          // reset pending dial group variables
   346          model.agentSettings.pendingDialGroupChange = 0;
   347          model.agentSettings.updateDGFromAdminUI = false;
   348      }
   349      // start ping call interval timer, sends message every 30 seconds
   350      // if this is not a manual outdial and we are not suppressing disposition pop
   351      if(model.currentCall.outdialDispositions && model.currentCall.outdialDispositions.dispositions && model.currentCall.outdialDispositions.dispositions.length > 0 && model.currentCall.surveyPopType !== "SUPPRESS"){
   352          model.pingIntervalId = setInterval(utils.sendPingCallMessage, 30000);
   353      }
   354      var formattedResponse = {
   355          message: "End Call Notification Received.",
   356          detail: "",
   357          uii: utils.getText(notif, "uii"),
   358          sessionId: utils.getText(notif, "session_id"),
   359          agentId: utils.getText(notif, "agent_id"),
   360          callDts: utils.getText(notif, "call_dts"),
   361          duration: model.currentCall.duration,
   362          termParty: model.currentCall.termParty,
   363          termReason: model.currentCall.termReason,
   364          recordingUrl: utils.getText(notif, "recording_url"),
   365          dispositionTimeout: utils.getText(notif, "disposition_timeout")
   366      };
   367      return formattedResponse;
   368  };
   369  var GatesChangeNotification = function() {
   370  };
   371  /*
   372   * This class is responsible for handling a gates change notification
   373   *
   374   * {
   375   *      "ui_notification":{
   376   *          "@message_id":"IQ10012016080817344100936",
   377   *          "@type":"GATES_CHANGE",
   378   *          "agent_id":{"#text":"1180958"},
   379   *          "gate_ids":{"#text":"11117,3"}
   380   *      }
   381   * }
   382   */
   383  GatesChangeNotification.prototype.processResponse = function(notification) {
   384      var model = UIModel.getInstance();
   385      var notif = notification.ui_notification;
   386      var newAssignedGates = [];
   387      var availableQueues = model.inboundSettings.availableQueues;
   388      var assignedGateIds = utils.getText(notif, "gate_ids");
   389      if(assignedGateIds !== ""){
   390          assignedGateIds = assignedGateIds.split(',');
   391      }
   392      for(var a = 0; a < assignedGateIds.length; a++){
   393          // find gate in avail list
   394          var id = assignedGateIds[a];
   395          var foundGate = utils.findObjById(availableQueues, id, "gateId");
   396          if(foundGate){
   397              newAssignedGates.push(foundGate);
   398          }else{
   399              // gate not in assigned list, add stub
   400              var gate = {
   401                  gateId: id,
   402                  gateName:"",
   403                  gateDesc:"",
   404                  defaultDestOverride:"",
   405                  isAgentSelectable:false
   406              };
   407              newAssignedGates.push(gate);
   408          }
   409      }
   410      model.inboundSettings.queues = JSON.parse(JSON.stringify(newAssignedGates));
   411      var formattedResponse = {
   412          agentId: utils.getText(notif, "agent_id"),
   413          message: "Gates Change notification received.",
   414          queues: newAssignedGates
   415      };
   416      return formattedResponse;
   417  };
   418  var GenericNotification = function() {
   419  };
   420  /*
   421   * This class is responsible for handling a generic notification
   422   *
   423   * {
   424   *      "ui_notification":{
   425   *          "@message_id":"IQ10012016080317400400011",
   426   *          "@response_to":"1c2fe39f-a31e-aff8-8d23-92a61c88270f",
   427   *          "@type":"GENERIC",
   428   *          "message_code":{"#text":"0"},
   429   *          "message":{"#text":"OK"},
   430   *          "detail":{"#text":"Pending Callback Successfully Cancelled."}
   431   *      }
   432   * }
   433   */
   434  GenericNotification.prototype.processResponse = function(notification) {
   435      var formattedResponse = utils.buildDefaultResponse(notification);
   436      // add message and detail if present
   437      formattedResponse.messageCode = utils.getText(notification.ui_notification,"message_code");
   438      return formattedResponse;
   439  };
   440  var NewCallNotification = function() {
   441  };
   442  /*
   443   * This class processes a "NEW-CALL" packet received from Intelliqueue. It will determine
   444   * if the call is a regular or monitoring call:
   445   * 		@Monitoring==true:  set state to ACTIVE-MONITORING, send NewMonitoringCall event
   446   * 		@Monitoring==false: set state to ACTIVE, send newcall packet and increment total calls
   447   *
   448   *  {"ui_notification":{
   449   *      "@message_id":"IQ982010020911335300027",
   450   *      "@response_to":"",
   451   *      "@type":"NEW-CALL",
   452   *      "uii":{"#text":"201002091133350139990000000010"},
   453   *      "ani":{"#text":"9548298548"},
   454   *      "dnis":{},
   455   *      "dial_dest":{"#text":"sip:+16789050673@sip.connectfirst.com"},
   456   *      "call_type":{"#text":"OUTBOUND"},
   457   *      "queue_dts":{"#text":"2010-02-09 11:33:53"},
   458   *      "queue_time":{"#text":"-1"},
   459   *      "agent_id":{"#text":"657"},
   460   *      "app_url":{},
   461   *      "is_monitoring":{"#text":"FALSE"},
   462   *      "script_id":{},
   463   *      "script_version":{},
   464   *      "survey_id":{},
   465   *      "survey_pop_type":{"#text":"SUPPRESS"},
   466   *      "message":{},
   467   *      "agent_recording":{"@default":"ON","@pause":"10","#text":"TRUE"},
   468   *      "hangup_on_disposition":{"#text":"FALSE"},
   469   *      "gate":{
   470   *          "@number":"17038",
   471   *          "name":{"#text":"AM Campaign"},
   472   *          "description":{}
   473   *      },
   474   *      "outdial_dispositions":{
   475   *          "@type":"CAMPAIGN|GATE",
   476   *          "disposition":[
   477   *              { "@contact_forwarding":"FALSE", "@disposition_id":"20556", "@is_complete":"1", "@is_default"="0", "@require_note"="0", "@save_survey"="1", "@xfer"="0", "#text":"Not Available"},
   478   *              { "@contact_forwarding":"FALSE", "@disposition_id":"20559", "@is_complete":"1", "@is_default"="1", "@require_note"="1", "@save_survey"="1", "@xfer"="0", #text":"Transfer Not Available"}
   479   *          ]
   480   *      },
   481   *      "requeue_shortcuts":{
   482   *          "requeue_shortcut":[
   483   *              { "@gate_id":"2", "@name":"test queue" "@skill_id":""}
   484   *          ]
   485   *      },
   486   *      "baggage":{
   487   *          "@allow_updates":"TRUE",
   488   *          "@show_lead_passes":"TRUE",
   489   *          "@show_list_name":"TRUE",
   490   *          "aux_phone":{},
   491   *          "aux_greeting":{},
   492   *          "aux_external_url":{},
   493   *          "aux_data1":{"#text":"BMAK"},
   494   *          "aux_data2":{"#text":"BMAK-041653-934"},
   495   *          "aux_data3":{"#text":"Call Ctr 1"},
   496   *          "aux_data4":{},
   497   *          "aux_data5":{},
   498   *          "extern_id":{"#text":"9548298548"},
   499   *          "lead_id":{"#text":"64306"},
   500   *          "lead_passes":{"#text":"1"},
   501   *          "first_name":{"#text":"Ryant"},
   502   *          "last_name":{"#text":"Taylor"},
   503   *          "mid_name":{},
   504   *          "address1":{"#text":"8010 Maryland Ave"},
   505   *          "address2":{},
   506   *          "city":{"#text":"Cleveland"},
   507   *          "state":{"#text":"OH"},
   508   *          "zip":{"#text":"44105"},
   509   *          "custom_labels":{
   510   *              "aux_1_label":{},
   511   *              "aux_2_label":{},
   512   *              "aux_3_label":{},
   513   *              "aux_4_label":{},
   514   *              "aux_5_label":{}
   515   *          }
   516   *      },
   517   *      "survey_response":{
   518   *          "@response_id":"24",
   519   *          "@survey_id":"1775",
   520   *          "details":{
   521   *              "detail":[
   522   *                  {"@element_id":"9001","@option_id":"0","#text":"Box 1"},
   523   *                  {"@element_id":"9002","@option_id":"0","#text":"Area 1"},
   524   *                  {"@element_id":"9003","@option_id":"6439"},
   525   *                  {"@element_id":"9004","@option_id":"6443"},
   526   *                  {"@element_id":"9004","@option_id":"6444"},
   527   *                  {"@element_id":"9005","@option_id":"6447"},
   528   *                  {"@element_id":"9006","@option_id":"0","#text":"11/20/2013"},
   529   *                  {"@element_id":"9015","@option_id":"0","#text":"Box 2"},
   530   *                  {"@element_id":"9016","@option_id":"0","#text":"Area 2"},
   531   *                  {"@element_id":"9017","@option_id":"6466"},
   532   *                  {"@element_id":"9018","@option_id":"6471"},
   533   *                  {"@element_id":"9018","@option_id":"6472"},
   534   *                  {"@element_id":"9019","@option_id":"6477"},
   535   *                  {"@element_id":"9020","@option_id":"0","#text":"11/21/2013"}
   536   *             ]
   537   *          }
   538   *      }
   539   *    }
   540   *  }
   541   */
   542  NewCallNotification.prototype.processResponse = function(notification) {
   543      var model = UIModel.getInstance();
   544      var notif = notification.ui_notification;
   545      // set up new call obj
   546      var newCall = {
   547          uii: utils.getText(notif,'uii'),
   548          agentId: utils.getText(notif,'agent_id'),
   549          dialDest: utils.getText(notif,'dial_dest'),
   550          queueDts: utils.getText(notif,'queue_dts'),
   551          queueTime: utils.getText(notif,'queue_time'),
   552          ani: utils.getText(notif,'ani'),
   553          dnis: utils.getText(notif,'dnis'),
   554          callType: utils.getText(notif,'call_type'),
   555          appUrl: utils.getText(notif,'app_url'),
   556          isMonitoring: utils.getText(notif,'is_monitoring'),
   557          allowHold: utils.getText(notif,'allow_hold'),
   558          allowTransfer: utils.getText(notif,'allow_transfer'),
   559          allowManualInternationalTransfer: utils.getText(notif,'allow_manual_international_transfer'),
   560          allowDirectAgentTransfer: utils.getText(notif,'allow_direct_agent_transfer'),
   561          allowHangup: utils.getText(notif,'allow_hangup'),
   562          allowRequeue: utils.getText(notif,'allow_requeue'),
   563          allowEndCallForEveryone: utils.getText(notif,'allow_endcallforeveryone'),
   564          scriptId: utils.getText(notif,'script_id'),
   565          scriptVersion: utils.getText(notif,'script_version'),
   566          surveyId: utils.getText(notif,'survey_id'),
   567          surveyPopType: utils.getText(notif,'survey_pop_type'),
   568          requeueType: utils.getText(notif,'requeue_type'),
   569          hangupOnDisposition: utils.getText(notif,'hangup_on_disposition')
   570      };
   571      if(newCall.isMonitoring) {
   572          newCall.monitoringType = utils.getText(notif,'monitoring_type');    // FULL, COACHING, MONITOR
   573      }
   574      // set collection values
   575      newCall.queue = utils.processResponseCollection(notification, 'ui_notification', 'gate')[0];
   576      newCall.agentRecording = utils.processResponseCollection(notification, 'ui_notification', 'agent_recording', 'agentRecording')[0];
   577      newCall.outdialDispositions = utils.processResponseCollection(notification, 'ui_notification', 'outdial_dispositions', 'disposition')[0];
   578      newCall.requeueShortcuts = utils.processResponseCollection(notification, 'ui_notification', 'requeue_shortcuts', 'requeueShortcut')[0] || [];
   579      newCall.baggage = utils.processResponseCollection(notification, 'ui_notification', 'baggage')[0];
   580      newCall.surveyResponse = utils.processResponseCollection(notification, 'ui_notification', 'survey_response', 'detail')[0];
   581      newCall.scriptResponse = {};
   582      newCall.transferPhoneBook = utils.processResponseCollection(notification, 'ui_notification', 'transfer_phone_book')[0];
   583      newCall.lead = utils.processResponseCollection(notification, 'ui_notification', 'lead')[0];
   584      // parse extra data correctly
   585      try {
   586          if(notif.lead && notif.lead.extra_data) {
   587              delete newCall.lead.extraDatas;
   588              newCall.lead.extraData = {};
   589              for(var key in notif.lead.extra_data) {
   590                  newCall.lead.extraData[key] = notif.lead.extra_data[key]['#text'];
   591              }
   592          }
   593      } catch(e) {
   594          console.warn('error parsing new call lead extra data: ' + e);
   595      }
   596      if(newCall.baggage) {
   597          // process custom labels correctly
   598          newCall.baggage.customLabels = {};
   599          var notifLabels = notif.baggage['custom_labels'];
   600          for(var key in notifLabels) {
   601              var result = '';
   602              if(notifLabels && notifLabels[key] && notifLabels[key]['#text']) {
   603                  result = notifLabels[key]['#text'];
   604              }
   605              newCall.baggage.customLabels[key] = result;
   606          }
   607      }
   608      // set saved script response if present
   609      try{
   610          var savedModel = JSON.parse(notif.script_result["#text"]).model;
   611          var results = {};
   612          var keys = Object.keys(savedModel);
   613          for(var idx = 0; idx < keys.length; idx++){
   614              var key = keys[idx];
   615              var value = savedModel[key].value;
   616              results[key] = value;
   617          }
   618          newCall.scriptResponse = results;
   619      }catch(err){}
   620      // fix phonebook format
   621      if(newCall.transferPhoneBook && newCall.transferPhoneBook.entrys){
   622          newCall.transferPhoneBook = newCall.transferPhoneBook.entrys;
   623      }
   624      // fix requeue shortcuts
   625      if(newCall.requeueShortcuts && newCall.requeueShortcuts.requeueShortcuts){
   626          newCall.requeueShortcuts = newCall.requeueShortcuts.requeueShortcuts;
   627      }
   628      // if only one disposition, convert to array
   629      if(newCall.outdialDispositions && newCall.outdialDispositions.disposition){
   630          newCall.outdialDispositions.dispositions = [newCall.outdialDispositions]
   631      }
   632      // convert numbers to boolean where applicable
   633      newCall.queue.isCampaign = newCall.queue.isCampaign === "1";
   634      if(newCall.outdialDispositions && newCall.outdialDispositions.dispositions){
   635          for(var d = 0; d < newCall.outdialDispositions.dispositions.length; d++) {
   636              var disp = newCall.outdialDispositions.dispositions[d];
   637              disp.isComplete = disp.isComplete === "1";
   638              disp.requireNote = disp.requireNote === "1";
   639              disp.saveSurvey = disp.saveSurvey === "1";
   640              disp.xfer = disp.xfer === "1";
   641              disp.isDefault = disp.isDefault === "1";
   642          }
   643      }
   644      // Build token map
   645      model.callTokens = buildCallTokenMap(notif, newCall);
   646      newCall.baggage = model.callTokens; // add all tokens to baggage
   647      // Is Monitoring Call?
   648      if(newCall.isMonitoring){
   649          model.agentSettings.callState = "ACTIVE-MONITORING";
   650      }else{
   651          model.agentSettings.callState = "ACTIVE";
   652          // check for preloaded transfer number
   653          if(newCall.baggage && newCall.baggage.auxPhone != ""){
   654              model.transferNumber = newCall.baggage.auxPhone;
   655          }
   656      }
   657      // Reset the current call counter for Agent Daily Stats
   658      model.agentDailyStats.currCallTime = 0;
   659      // todo handle scripting??
   660      model.currentCall = newCall;
   661      return newCall;
   662  };
   663  function buildCallTokenMap(notif, newCall){
   664      var model = UIModel.getInstance();
   665      var tokens = newCall.baggage || {}; // seed with baggage values
   666      if(notif.baggage && notif.baggage.generic_key_value_pairs){
   667          var keyValuePairs = [];
   668          var keyValuePairsStr = utils.getText(notif.baggage, 'generic_key_value_pairs');
   669          if (keyValuePairsStr.length > 0){
   670              keyValuePairs = utils.parseKeyValuePairsFromString(keyValuePairsStr, "|", "::");
   671          }
   672          for(var keyValue in keyValuePairs){
   673              tokens[keyValue] = keyValuePairs[keyValue];
   674          }
   675      }
   676      tokens["ani"] = newCall.ani;
   677      tokens["dnis"] = newCall.dnis;
   678      tokens["uii"] = newCall.uii;
   679      try{
   680          if(newCall.queue.number){
   681              tokens["sourceId"] = newCall.queue.number || "";
   682              tokens["sourceName"] = newCall.queue.name || "";
   683              tokens["sourceDesc"] = newCall.queue.description || "";
   684              if(newCall.queue.isCampaign === "1" || newCall.queue.isCampaign === true){
   685                  tokens["sourceType"] = "OUTBOUND";
   686              }else{
   687                  tokens["sourceType"] = "INBOUND";
   688              }
   689          }else{
   690              tokens["sourceId"] = "0";
   691              tokens["sourceType"] = "MANUAL";
   692              tokens["sourceName"] = "";
   693              tokens["sourceDesc"] = "";
   694          }
   695      }catch(any){
   696          console.error("There was an error processing source tokenization", + any);
   697      }
   698      try{
   699          tokens["agentFirstName"] = model.agentSettings.firstName;
   700          tokens["agentLastName"] = model.agentSettings.lastName;
   701          tokens["agentExternalId"] = model.agentSettings.externalAgentId;
   702          tokens["agentType"] = model.agentSettings.agentType;
   703          tokens["agentEmail"] = model.agentSettings.email;
   704          tokens["agentUserName"] = model.agentSettings.username;
   705      }catch(any){
   706          console.error("There was an error parsing tokens for agent info. ", any);
   707      }
   708      return tokens;
   709  }
   710  function isCampaign(gate){
   711      if (gate && gate.isCampaign){
   712          return gate.isCampaign === "1" || gate.isCampaign === true;
   713      }
   714      return false;
   715  }
   716  var PendingChatDispNotification = function() {
   717  };
   718  /*
   719   * This class is responsible for handling a generic notification
   720   *
   721   *  {
   722   *       "ui_notification":{
   723   *           "@message_id":"IQD01DEV2018062912352800014",
   724   *           "@type":"PENDING_CHAT_DISP",
   725   *           "agent_id":{ "#text":"1182160" },
   726   *           "uii":{ "#text":"201806291234550147950000000000" },
   727   *           "status":{ "#text":"false" }
   728   *       }
   729   *   }
   730   */
   731  PendingChatDispNotification.prototype.processResponse = function(notification) {
   732      var formattedResponse = {};
   733      formattedResponse.agentId = utils.getText(notification.ui_notification,"agent_id");
   734      formattedResponse.uii = utils.getText(notification.ui_notification,"uii");
   735      formattedResponse.status = utils.getText(notification.ui_notification,"status") === 'true';
   736      return formattedResponse;
   737  };
   738  var PendingDispNotification = function() {
   739  };
   740  /*
   741   * This class is responsible for handling a generic notification
   742   *
   743   * {
   744   *      "ui_notification":{
   745   *          "@message_id":"IQ10012016080317400400011",
   746   *          "@type":"PENDING_DISP",
   747   *          "agent_id":{"#text":"3"},
   748   *          "status":{"#text":"false"}
   749   *      }
   750   * }
   751   */
   752  PendingDispNotification.prototype.processResponse = function(notification) {
   753      var formattedResponse = {};
   754      formattedResponse.agentId = utils.getText(notification.ui_notification,"agent_id");
   755      formattedResponse.status = utils.getText(notification.ui_notification,"status");
   756      return formattedResponse;
   757  };
   758  var PreviewLeadStateNotification = function() {
   759  };
   760  /*
   761   * This class is responsible for processing the lead state packet
   762   * received from intelliqueue. It will decide what type of leads are
   763   * being processed, and depending on if the callback is true or false, it will
   764   * call the appropriate form to update the lead state.
   765   *
   766   * {
   767   *      "ui_notification":{
   768   *          "@type":"PREVIEW-LEAD-STATE",
   769   *          "@call_type":"MANUAL|PREVIEW",
   770   *          "@message_id":"IQ10012016092715393600184",
   771   *          "request_id":{"#text":"IQ10012016092715390900179"},
   772   *          "lead_state":{"#text":"ANSWER"},
   773   *          "callback":{"#text":"FALSE"}
   774   *      }
   775   *   }
   776   * }
   777   */
   778  PreviewLeadStateNotification.prototype.processResponse = function(notification) {
   779      var notif = notification.ui_notification;
   780      UIModel.getInstance().agentSettings.onManualOutdial = true;
   781      var response = {
   782          callType: notif['@call_type'],
   783          messageId: notif['@message_id'],
   784          requestId: utils.getText(notif, "request_id"),
   785          leadState: utils.getText(notif,"lead_state"),
   786          callback: utils.getText(notif,"callback")
   787      };
   788      return response;
   789  };
   790  var ReverseMatchNotification = function() {
   791  };
   792  /*
   793   * This class is responsible for processing a REVERSE_MATCH packet from IQ. It
   794   * will log the packet was rec'd, save the packet to the UIModel for use by
   795   * components like the WhosCallingForm
   796   * {
   797   *      "ui_notification":{
   798   *          "@message_id":"IQ10012016080317400400011",
   799   *          "@response_to":"1c2fe39f-a31e-aff8-8d23-92a61c88270f",
   800   *          "@type":"REVERSE_MATCH",
   801   *          "first_name":{"#text":""},
   802   *          "mid_name":{"#text":""},
   803   *          "last_name":{"#text":""},
   804   *          "address1":{"#text":""},
   805   *          "address2":{"#text":""},
   806   *          "city":{"#text":""},
   807   *          "state":{"#text":""},
   808   *          "zip":{"#text":""},
   809   *          "business_name":{"#text":""}
   810   *      }
   811   * }
   812   */
   813  ReverseMatchNotification.prototype.processResponse = function(notification) {
   814      var notif = notification.ui_notification;
   815      var model = UIModel.getInstance();
   816      model.tokens["first_name"] = utils.getText(notif,'first_name');
   817      model.tokens["mid_name"] = utils.getText(notif,'mid_name');
   818      model.tokens["last_name"] = utils.getText(notif,'last_name');
   819      model.tokens["address1"] = utils.getText(notif,'address1');
   820      model.tokens["address2"] = utils.getText(notif,'address2');
   821      model.tokens["suffix"] = utils.getText(notif,'suffix');
   822      model.tokens["title"] = utils.getText(notif,'title');
   823      model.tokens["city"] = utils.getText(notif,'city');
   824      model.tokens["state"] = utils.getText(notif,'state');
   825      model.tokens["zip"] = utils.getText(notif,'zip');
   826      model.tokens["business_name"] = utils.getText(notif,'business_name');
   827      return model.tokens;
   828  };
   829  var TcpaSafeLeadStateNotification = function() {
   830  };
   831  /*
   832   * This class is responsible for processing the lead state packet
   833   * received from intelliqueue. It will decide what type of leads are
   834   * being processed, and depending on if the callback is true or false, it will
   835   * call the appropriate form to update the lead state.
   836   *
   837   * {
   838   *      "ui_notification":{
   839   *          "@message_id":"IQ10012016080317400400011",
   840   *          "@type":"TCPA-SAFE-LEAD-STATE",
   841   *          "@call_type":"MANUAL|TCPA-SAFE",
   842   *          "request_id":{"#text":""},
   843   *          "lead_state":{"#text":"CALLING"},
   844   *          "callback":{"#text":"false"}
   845   *      }
   846   * }
   847   */
   848  TcpaSafeLeadStateNotification.prototype.processResponse = function(notification) {
   849      var notif = notification.ui_notification;
   850      var response = {
   851          callType: notif['@call_type'],
   852          messageId: notif['@message_id'],
   853          requestId: utils.getText(notif, "request_id"),
   854          leadState: utils.getText(notif,"lead_state"),
   855          callback: utils.getText(notif,"callback")
   856      };
   857      return response;
   858  };
   859  var AckRequest = function(audioType, agentId, uii, monitorAgentId) {
   860      this.audioType = audioType || "FULL";
   861      this.agentId = agentId;
   862      this.uii = uii;
   863      this.monitorAgentId = monitorAgentId;
   864  };
   865  /*
   866   * This class processes ACK packets rec'd from IQ.
   867   * This is a callback triggered by certain actions like
   868   * sending dispositions or script results.
   869   * NOTE: uii is added in utils message processing.
   870   *
   871   * {"ui_response":{
   872   *      "@message_id":"IQ982008090317393001252",
   873   *      "@response_to":"1112222",
   874   *      "@type":"ACK",
   875   *      "type":{"#text":"CHAT-DISPOSITION|INBOUND-DISPOSITION|OUTDIAL-DISPOSITION|SCRIPT-RESULT"},
   876   *      "status":{"#text":"OK|FAILURE"},
   877   *      "message":{"#text":""},
   878   *      "detail":{}
   879   *    }
   880   * }
   881   */
   882  AckRequest.prototype.processResponse = function(response) {
   883      var resp = response.ui_response;
   884      var formattedResponse = utils.buildDefaultResponse(response);
   885      formattedResponse.type = utils.getText(resp, 'type');
   886      if(formattedResponse.status === "OK"){
   887          utils.logMessage(LOG_LEVELS.DEBUG, formattedResponse.message, response);
   888      }else{
   889          utils.logMessage(LOG_LEVELS.WARN, formattedResponse.message + ': ' + formattedResponse.detail, response);
   890      }
   891      return formattedResponse;
   892  };
   893  var AgentStateRequest = function(agentState, agentAuxState) {
   894      if(agentState.toUpperCase() == "ON-BREAK" && UIModel.getInstance().onCall == true){
   895          this.agentState = "BREAK-AFTER-CALL";
   896          this.agentAuxState = "";
   897      }else{
   898          this.agentState = agentState.toUpperCase() || "";
   899          this.agentAuxState = agentAuxState || "";
   900      }
   901  };
   902  AgentStateRequest.prototype.formatJSON = function() {
   903      var msg = {
   904          "ui_request": {
   905              "@destination":"IQ",
   906              "@type":MESSAGE_TYPES.AGENT_STATE,
   907              "@message_id":utils.getMessageId(),
   908              "response_to":"",
   909              "agent_id":{
   910                  "#text":UIModel.getInstance().agentSettings.agentId
   911              },
   912              "state":{
   913                  "#text":this.agentState
   914              },
   915              "agent_aux_state":{
   916                  "#text":this.agentAuxState
   917              }
   918          }
   919      };
   920      return JSON.stringify(msg);
   921  };
   922  /*
   923   * This class processes AGENT-STATE packets rec'd from IQ. It will check the state of the
   924   * packet and then set the state on the model. It will also check for deferred surveys,
   925   * if one is found it will load it at this point.
   926   *
   927   * {"ui_response":{
   928   *      "@message_id":"IQ982008082817165103294",
   929   *      "@type":"AGENT-STATE",
   930   *      "status":{"#text":"OK"},
   931   *      "message":{},
   932   *      "detail":{},
   933   *      "agent_id":{"#text":"1856"},
   934   *      "prev_state":{"#text":"ENGAGED"},
   935   *      "current_state":{"#text":"WORKING"},
   936   *      "agent_aux_state":{"#text":"Offhook Work"},
   937   *      "prev_aux_state":{}
   938   *   }
   939   * }
   940   */
   941  AgentStateRequest.prototype.processResponse = function(response) {
   942      var resp = response.ui_response;
   943      var status = utils.getText(resp, "status");
   944      var prevState = utils.getText(resp, "prev_state");
   945      var currState = utils.getText(resp, "current_state");
   946      var prevAuxState = utils.getText(resp, "prev_aux_state");
   947      var currAuxState = utils.getText(resp, "agent_aux_state");
   948      var model = UIModel.getInstance();
   949      // add message and detail if present
   950      var formattedResponse = utils.buildDefaultResponse(response);
   951      formattedResponse.agentId = response.ui_response.agent_id['#text'] || "";
   952      formattedResponse.previousState = prevState;
   953      formattedResponse.currentState = currState;
   954      formattedResponse.previousAuxState = prevAuxState;
   955      formattedResponse.currentAuxState = currAuxState;
   956      if(status=="OK"){
   957          var prevStateStr = prevState;
   958          var currStateStr = currState;
   959          if(prevAuxState.length > 0){
   960              prevStateStr = prevAuxState;
   961          }
   962          if(currAuxState.length > 0){
   963              currStateStr = currAuxState;
   964          }
   965          // Update the state in the UIModel
   966          model.agentSettings.currentState = currState;
   967          model.agentSettings.currentStateLabel = currAuxState;
   968          model.agentStatePacket = response;
   969      }else{
   970          if(formattedResponse.message === ""){
   971              formattedResponse.message = "Unable to change agent state";
   972          }
   973          // log message response
   974          var message = "Unable to change agent state. " + formattedResponse.detail;
   975          utils.logMessage(LOG_LEVELS.WARN, message, response);
   976      }
   977      return formattedResponse;
   978  };
   979  var BargeInRequest = function(audioType, agentId, uii, monitorAgentId) {
   980      this.audioType = audioType || "FULL";
   981      this.agentId = agentId;
   982      this.uii = uii;
   983      this.monitorAgentId = monitorAgentId;
   984  };
   985  /*
   986   *
   987   * {"ui_request":{
   988   *      "@destination":"IQ",
   989   *      "@message_id":"UIV22008931055822",
   990   *      "@response_to":"",
   991   *      "@type":"BARGE-IN",
   992   *      "agent_id":{"#text":"94"},
   993   *      "uii":{"#text":"200809031054510000000900020961"},
   994   *      "audio_state":{"#text":"FULL"},
   995   *      "monitor_agent_id":{"#text":"1856"}
   996   *    }
   997   * }
   998   */
   999  BargeInRequest.prototype.formatJSON = function() {
  1000      var model = UIModel.getInstance();
  1001      var msg = {
  1002          "ui_request": {
  1003              "@destination":"IQ",
  1004              "@type":MESSAGE_TYPES.BARGE_IN,
  1005              "@message_id":utils.getMessageId(),
  1006              "@response_to":"",
  1007              "agent_id":{
  1008                  "#text":utils.toString(this.agentId)
  1009              },
  1010              "uii":{
  1011                  "#text":utils.toString(this.uii)
  1012              },
  1013              "audio_state":{
  1014                  "#text":utils.toString(this.audioType)
  1015              },
  1016              "monitor_agent_id":{
  1017                  "#text":utils.toString(this.monitorAgentId)
  1018              }
  1019          }
  1020      };
  1021      return JSON.stringify(msg);
  1022  };
  1023  /*
  1024   * This class processes BARGE-IN packets rec'd from IQ.
  1025   *
  1026   * {"ui_response":{
  1027   *      "@message_id":"IQ982008090317393001252",
  1028   *      "@response_to":"",
  1029   *      "@type":"BARGE-IN",
  1030   *      "agent_id":{"#text":"94"},
  1031   *      "uii":{},
  1032   *      "status":{"#text":"OK"},
  1033   *      "message":{"#text":"Barge-In processed successfully!"},
  1034   *      "detail":{}
  1035   *    }
  1036   * }
  1037   */
  1038  BargeInRequest.prototype.processResponse = function(response) {
  1039      var resp = response.ui_response;
  1040      var formattedResponse = utils.buildDefaultResponse(response);
  1041      formattedResponse.agentId = utils.getText(resp, 'agent_id');
  1042      formattedResponse.uii = utils.getText(resp, 'uii');
  1043      if(formattedResponse.status === "OK"){
  1044          utils.logMessage(LOG_LEVELS.DEBUG, formattedResponse.message, response);
  1045      }else{
  1046          utils.logMessage(LOG_LEVELS.WARN, "There was an error processing the Barge-In request. " + formattedResponse.detail, response);
  1047      }
  1048      return formattedResponse;
  1049  };
  1050  var CallNotesRequest = function(notes) {
  1051      this.notes = notes;
  1052  };
  1053  /*
  1054  * This event is responsible for allowing an agent to tag a call with notes
  1055  */
  1056  CallNotesRequest.prototype.formatJSON = function() {
  1057      var model = UIModel.getInstance();
  1058      var msg = {
  1059          "ui_request": {
  1060              "@destination":"IQ",
  1061              "@message_id":utils.getMessageId(),
  1062              "response_to":"",
  1063              "@type":MESSAGE_TYPES.CALL_NOTES,
  1064              "agent_id": {
  1065                  "#text" : utils.toString(model.agentSettings.agentId)
  1066              },
  1067              "uii": {
  1068                  "#text" : utils.toString(model.currentCall.uii)
  1069              },
  1070              "notes": {
  1071                  "#text" : utils.toString(this.notes)
  1072              }
  1073          }
  1074      };
  1075      return JSON.stringify(msg);
  1076  };
  1077  /*
  1078   * This class process CALL-NOTES packets rec'd from IntelliQueue.
  1079   *
  1080   * {"ui_response":{
  1081   *      "@message_id":"IQ982008082817165103294",
  1082   *      "@type":"CALL-NOTES",
  1083   *      "status":{"#text":"OK"},
  1084   *      "message":{},
  1085   *      "detail":{}
  1086   *   }
  1087   * }
  1088   */
  1089  CallNotesRequest.prototype.processResponse = function(response) {
  1090      var formattedResponse = utils.buildDefaultResponse(response);
  1091      if(formattedResponse.status === "OK"){
  1092          formattedResponse.message = "Call notes have been updated.";
  1093          formattedResponse.type = "INFO_EVENT";
  1094      }else{
  1095          formattedResponse.type = "ERROR_EVENT";
  1096          formattedResponse.message = "Unable to update notes.";
  1097      }
  1098      return formattedResponse;
  1099  };
  1100  var CallbackCancelRequest = function(leadId, agentId) {
  1101      this.agentId = agentId || UIModel.getInstance().agentSettings.agentId;
  1102      this.leadId = leadId;
  1103  };
  1104  CallbackCancelRequest.prototype.formatJSON = function() {
  1105      var msg = {
  1106          "ui_request": {
  1107              "@destination":"IQ",
  1108              "@type":MESSAGE_TYPES.CALLBACK_CANCEL,
  1109              "@message_id":utils.getMessageId(),
  1110              "response_to":"",
  1111              "agent_id":{
  1112                  "#text":this.agentId    
  1113              },
  1114              "lead_id":{
  1115                  "#text":this.leadId
  1116              }
  1117          }
  1118      };
  1119      return JSON.stringify(msg);
  1120  };
  1121  // NOTE: cancel callback response sent as a generic notification message
  1122  var CallbacksPendingRequest = function(agentId) {
  1123      this.agentId = agentId || UIModel.getInstance().agentSettings.agentId;
  1124  };
  1125  CallbacksPendingRequest.prototype.formatJSON = function() {
  1126      var msg = {
  1127          "ui_request": {
  1128              "@destination":"IQ",
  1129              "@type":MESSAGE_TYPES.CALLBACK_PENDING,
  1130              "@message_id":utils.getMessageId(),
  1131              "response_to":"",
  1132              "agent_id":{
  1133                  "#text":this.agentId
  1134              }
  1135          }
  1136      };
  1137      return JSON.stringify(msg);
  1138  };
  1139  /*
  1140   * This class is responsible for handling an PENDING-CALLBACKS response packet from IntelliQueue.
  1141   *
  1142   * {"ui_response":{
  1143   *      "@message_id":"IQ982008091512353000875",
  1144   *      "@response_to":"UIV220089151235539",
  1145   *      "@type":"PENDING-CALLBACKS",
  1146   *      "lead":{
  1147   *          "@aux_data1":"",
  1148   *          "@aux_data2":"",
  1149   *          "@aux_data3":"",
  1150   *          "@aux_data4":"",
  1151   *          "@aux_data5":"",
  1152   *          "@destination":"5555555555",
  1153   *          "@dial_group_id":"",
  1154   *          "@dial_group_name":"",
  1155   *          "@dial_time":"2016-08-03 10:00",
  1156   *          "@extern_id":"",
  1157   *          "@lead_id":"",
  1158   *          "lead_id":{},
  1159   *          "extern_id":{},
  1160   *          "extern_id":{},
  1161   *          "first_name":{},
  1162   *          "mid_name":{},
  1163   *          "last_name":{},
  1164   *          "suffix":{},
  1165   *          "title":{},
  1166   *          "address1":{},
  1167   *          "address2":{},
  1168   *          "city":{},
  1169   *          "state":{},
  1170   *          "zip":{},
  1171   *          "gate_keeper":{}
  1172   *      }
  1173   *   }
  1174   * }
  1175   */
  1176  CallbacksPendingRequest.prototype.processResponse = function(response) {
  1177      var leadsRaw = response.ui_response.lead;
  1178      var leads = [];
  1179      if(!Array.isArray(leadsRaw)) {
  1180          leadsRaw = [leadsRaw];
  1181      }
  1182      for(var l = 0; l < leadsRaw.length; l++){
  1183          var leadRaw = leadsRaw[l];
  1184          if (leadRaw == null) {
  1185              continue;
  1186          }
  1187          leads.push(parseLead(leadRaw));
  1188      }
  1189      UIModel.getInstance().agentSettings.pendingCallbacks = JSON.parse(JSON.stringify(leads));
  1190      return UIModel.getInstance().agentSettings.pendingCallbacks;
  1191  };
  1192  function parseLead(leadRaw){
  1193      var lead = {
  1194          auxData1 : leadRaw['@aux_data1'],
  1195          auxData2 : leadRaw['@aux_data2'],
  1196          auxData3 : leadRaw['@aux_data3'],
  1197          auxData4 : leadRaw['@aux_data4'],
  1198          auxData5 : leadRaw['@aux_data5'],
  1199          destination : leadRaw['@destination'],
  1200          dialGroupId : leadRaw['@dial_group_id'],
  1201          dialGroupName : leadRaw['@dial_group_name'],
  1202          dialTime : leadRaw['@dial_time'],
  1203          externId : leadRaw['@extern_id'],
  1204          leadId : leadRaw['@lead_id'],
  1205          firstName : utils.getText(leadRaw, "first_name"),
  1206          midName : utils.getText(leadRaw, "mid_name"),
  1207          lastName : utils.getText(leadRaw, "last_name"),
  1208          sufix : utils.getText(leadRaw, "suffix"),
  1209          title : utils.getText(leadRaw, "title"),
  1210          address1 : utils.getText(leadRaw, "address1"),
  1211          address2 : utils.getText(leadRaw, "address2"),
  1212          city : utils.getText(leadRaw, "city"),
  1213          state : utils.getText(leadRaw, "state"),
  1214          zip : utils.getText(leadRaw, "zip"),
  1215          gateKeeper : utils.getText(leadRaw, "gate_keeper")
  1216      };
  1217      return lead;
  1218  }
  1219  /*
  1220   * This request is used to get the list of dispositions for a given campaign
  1221   * E.g. in the lead search form for manual passes
  1222   *
  1223   */
  1224  var CampaignDispositionsRequest = function(campaignId) {
  1225      this.agentId = UIModel.getInstance().agentSettings.agentId;
  1226      this.campaignId = campaignId;
  1227  };
  1228  CampaignDispositionsRequest.prototype.formatJSON = function() {
  1229      var msg = {
  1230          "ui_request": {
  1231              "@destination":"IQ",
  1232              "@type":MESSAGE_TYPES.CAMPAIGN_DISPOSITIONS,
  1233              "@message_id":utils.getMessageId(),
  1234              "response_to":"",
  1235              "agent_id":{
  1236                  "#text":utils.toString(this.agentId)
  1237              },
  1238              "campaign_id": {
  1239                  "#text":utils.toString(this.campaignId)
  1240              }
  1241          }
  1242      };
  1243      return JSON.stringify(msg);
  1244  };
  1245  /*
  1246   * This class is responsible for handling CAMPAIGN-DISPOSITIONS packets received
  1247   * from IntelliQueue. It will save a copy of it in the UIModel.
  1248   *
  1249   * {"ui_response":{
  1250   *      "@campaign_id":"60403",
  1251   *      "@message_id":"IQ10012016081813480400006",
  1252   *      "@response_to":"0b61c3ca-c4fc-9942-c139-da4978053c9d",
  1253   *      "@type":"CAMPAIGN-DISPOSITIONS",
  1254   *      "outdial_dispositions":{
  1255   *          "disposition":[
  1256   *              {"@disposition_id":"1","#text":"requeue"},
  1257   *              {"@disposition_id":"2","#text":"complete"}
  1258   *          ]
  1259   *       }
  1260   *    }
  1261   * }
  1262   */
  1263  CampaignDispositionsRequest.prototype.processResponse = function(response) {
  1264      var resp = response.ui_response;
  1265      var model = UIModel.getInstance();
  1266      var dispositions = utils.processResponseCollection(resp, 'outdial_dispositions', 'disposition', 'disposition');
  1267      model.outboundSettings.campaignDispositions = dispositions;
  1268      return dispositions;
  1269  };
  1270  var ChatStateRequest = function(chatState) {
  1271      this.chatState = (chatState && chatState.toUpperCase()) || "";
  1272  };
  1273  ChatStateRequest.prototype.formatJSON = function() {
  1274      var msg = {
  1275          "ui_request": {
  1276              "@destination":"IQ",
  1277              "@type":MESSAGE_TYPES.CHAT_STATE,
  1278              "@message_id":utils.getMessageId(),
  1279              "response_to":"",
  1280              "agent_id":{
  1281                  "#text":UIModel.getInstance().agentSettings.agentId
  1282              },
  1283              "state":{
  1284                  "#text":this.chatState
  1285              }
  1286          }
  1287      };
  1288      return JSON.stringify(msg);
  1289  };
  1290  /*
  1291   * This class processes CHAT-STATE packets rec'd from IQ. It will check the state of the
  1292   * packet and then set the state on the model.
  1293   *
  1294   * {"ui_response":{
  1295   *      "@message_id":"IQ982008082817165103294",
  1296   *      "@type":"AGENT-STATE",
  1297   *      "status":{"#text":"OK"},
  1298   *      "message":{},
  1299   *      "detail":{},
  1300   *      "agent_id":{"#text":"1856"},
  1301   *      "prev_state":{"#text":"CHAT-PRESENTED"},
  1302   *      "current_state":{"#text":"CHAT-ENGAGED"}
  1303   *   }
  1304   * }
  1305   */
  1306  ChatStateRequest.prototype.processResponse = function(response) {
  1307      var resp = response.ui_response;
  1308      var status = utils.getText(resp, "status");
  1309      var prevState = utils.getText(resp, "prev_state");
  1310      var currState = utils.getText(resp, "current_state");
  1311      var model = UIModel.getInstance();
  1312      // add message and detail if present
  1313      var formattedResponse = utils.buildDefaultResponse(response);
  1314      formattedResponse.agentId = response.ui_response.agent_id['#text'] || "";
  1315      formattedResponse.previousState = prevState;
  1316      formattedResponse.currentState = currState;
  1317      if(status=="OK"){
  1318          // Update the state in the UIModel
  1319          model.agentSettings.currentChatState = currState;
  1320          model.chatStatePacket = response;
  1321      }else{
  1322          if(formattedResponse.message === ""){
  1323              formattedResponse.message = "Unable to change chat state";
  1324          }
  1325          // log message response
  1326          var message = "Unable to change chat state. " + formattedResponse.detail;
  1327          utils.logMessage(LOG_LEVELS.WARN, message, response);
  1328      }
  1329      return formattedResponse;
  1330  };
  1331  var XferColdRequest = function(dialDest, callerId, sipHeaders, countryId) {
  1332      this.dialDest = dialDest;
  1333      this.callerId = callerId || "";
  1334      this.sipHeaders = sipHeaders || [];
  1335      this.countryId = countryId || "";
  1336  };
  1337  XferColdRequest.prototype.formatJSON = function() {
  1338      var fields = [];
  1339      for(var i =0; i < this.sipHeaders.length; i++){
  1340          var fieldObj = this.sipHeaders[i];
  1341          fields.push({ '@name' : utils.toString(fieldObj.name), '@value' : utils.toString(fieldObj.value)});
  1342      }
  1343      var msg = {
  1344          "ui_request": {
  1345              "@destination":"IQ",
  1346              "@type":MESSAGE_TYPES.XFER_COLD,
  1347              "@message_id":utils.getMessageId(),
  1348              "@response_to":"",
  1349              "agent_id":{
  1350                  "#text":UIModel.getInstance().agentSettings.agentId
  1351              },
  1352              "uii":{
  1353                  "#text":UIModel.getInstance().currentCall.uii
  1354              },
  1355              "dial_dest":{
  1356                  "#text":utils.toString(this.dialDest)
  1357              },
  1358              "caller_id":{
  1359                  "#text":utils.toString(this.callerId)
  1360              },
  1361              "country_id": {
  1362                  "#text":utils.toString(this.countryId)
  1363              },
  1364              "xfer_header": fields
  1365          }
  1366      };
  1367      return JSON.stringify(msg);
  1368  };
  1369  /*
  1370   * This class processes COLD-XFER packets rec'd from IQ.
  1371   *
  1372   * {"ui_response":{
  1373   *      "@message_id":"IQ10012016082314475000219",
  1374   *      "@response_to":"",
  1375   *      "@type":"COLD-XFER",
  1376   *      "agent_id":{"#text":"1"},
  1377   *      "uii":{"#text":"201608231447590139000000000200"},
  1378   *      "session_id":{"#text":"3"},
  1379   *      "status":{"#text":"OK"},
  1380   *      "dial_dest":{"#text":"3038593775"},
  1381   *      "message":{"#text":"OK"},
  1382   *      "detail":{}
  1383   *   }
  1384   * }
  1385   */
  1386  XferColdRequest.prototype.processResponse = function(response) {
  1387      var resp = response.ui_response;
  1388      var formattedResponse = utils.buildDefaultResponse(response);
  1389      formattedResponse.agentId = utils.getText(resp, 'agent_id');
  1390      formattedResponse.uii = utils.getText(resp, 'uii');
  1391      formattedResponse.sessionId = utils.getText(resp, 'session_id');
  1392      formattedResponse.dialDest = utils.getText(resp, 'dial_dest');
  1393      if(formattedResponse.status === "OK"){
  1394      }else{
  1395          // log message response
  1396          var message = "There was an error processing the Cold Xfer request. " + formattedResponse.message + " : " + formattedResponse.detail;
  1397          utils.logMessage(LOG_LEVELS.WARN, message, response);
  1398      }
  1399      return formattedResponse;
  1400  };
  1401  var ConfigRequest = function(dialDest, queueIds, chatIds, skillProfileId, dialGroupId, updateFromAdminUI, isForce) {
  1402      this.queueIds = queueIds || [];
  1403      this.chatIds = chatIds || [];
  1404      this.skillProfileId = skillProfileId || "";
  1405      this.dialGroupId = dialGroupId || "";
  1406      this.dialDest = dialDest || "";
  1407      this.updateFromAdminUI = updateFromAdminUI || false;
  1408      this.loginType = "NO-SELECTION";
  1409      this.updateLogin = false;
  1410      this.isForce = isForce;
  1411      // Remove any ids agent doesn't have access to
  1412      var model = UIModel.getInstance();
  1413      this.queueIds = utils.checkExistingIds(model.inboundSettings.availableQueues, this.queueIds, "gateId");
  1414      this.chatIds = utils.checkExistingIds(model.chatSettings.availableChatQueues, this.chatIds, "chatQueueId");
  1415      this.skillProfileId = utils.checkExistingIds(model.inboundSettings.availableSkillProfiles, [this.skillProfileId], "profileId")[0] || "";
  1416      this.dialGroupId = utils.checkExistingIds(model.outboundSettings.availableOutdialGroups, [this.dialGroupId], "dialGroupId")[0] || "";
  1417      // Set loginType value
  1418      if(this.queueIds.length > 0 && this.dialGroupId !== ""){
  1419          this.loginType = "BLENDED";
  1420      } else if(this.queueIds.length > 0){
  1421          this.loginType = "INBOUND";
  1422      } else if(this.dialGroupId !== ""){
  1423          this.loginType = "OUTBOUND";
  1424      } else if(this.chatIds.length > 0){
  1425          this.loginType = "CHAT";
  1426      } else {
  1427          this.loginType = "NO-SELECTION";
  1428      }
  1429      // set updateLogin value
  1430      if(model.agentSettings.isLoggedIn){
  1431          this.updateLogin = true;
  1432      }
  1433      // validate dialDest is sip or 10-digit num
  1434      if(!utils.validateDest(this.dialDest)){
  1435          utils.logMessage(LOG_LEVELS.WARN, "dialDest [" + this.dialDest + "] must be a valid sip or 10-digit DID", "");
  1436      }
  1437  };
  1438  ConfigRequest.prototype.formatJSON = function() {
  1439      var msg = {
  1440          "ui_request":{
  1441              "@destination":"IQ",
  1442              "@type":MESSAGE_TYPES.LOGIN,
  1443              "@message_id":utils.getMessageId(),
  1444              "response_to":"",
  1445              "agent_id":{
  1446                  "#text":utils.toString(UIModel.getInstance().agentSettings.agentId)
  1447              },
  1448              "agent_pwd":{
  1449                  "#text": UIModel.getInstance().loginRequest.password
  1450              },
  1451              "dial_dest":{
  1452                  "#text":utils.toString(this.dialDest)
  1453              },
  1454              "login_type":{
  1455                  "#text":this.loginType
  1456              },
  1457              "update_login":{
  1458                  "#text":utils.toString(this.updateLogin)
  1459              },
  1460              "outdial_group_id":{
  1461                  "#text":utils.toString(this.dialGroupId)
  1462              },
  1463              "skill_profile_id":{
  1464                  "#text":utils.toString(this.skillProfileId)
  1465              },
  1466              "update_from_adminui":{
  1467                  "#text":utils.toString(this.updateFromAdminUI)
  1468              },
  1469              "agent_platform_id" : {
  1470                  "#text" : utils.toString(2) //Hard-coded platformId
  1471              },
  1472              "is_force" : {
  1473                  "#text" : utils.toString(this.isForce)
  1474              }
  1475          }
  1476      };
  1477      // add arrays
  1478      var queueIds = [];
  1479      for(var i = 0; i < this.queueIds.length; i++){
  1480          if(this.queueIds[i] !== ""){
  1481              queueIds.push( { "#text": utils.toString(this.queueIds[i]) } );
  1482          }
  1483      }
  1484      if(queueIds.length > 0){
  1485          msg.ui_request.gates = { "gate_id" : queueIds };
  1486      }else{
  1487          msg.ui_request.gates = {};
  1488      }
  1489      var chatIds = [];
  1490      for(var i = 0; i < this.chatIds.length; i++){
  1491          if(this.chatIds[i] !== "") {
  1492              chatIds.push( {"#text": utils.toString(this.chatIds[i]) } );
  1493          }
  1494      }
  1495      if(chatIds.length > 0) {
  1496          msg.ui_request.chat_queues = {"chat_queue_id": chatIds};
  1497      }else{
  1498          msg.ui_request.chat_queues = {};
  1499      }
  1500      return JSON.stringify(msg);
  1501  };
  1502  /*
  1503   * This function is responsible for handling the response to Login from IntelliQueue.
  1504   *
  1505   * {"ui_response":{
  1506   *      "@message_id":"IQ10012016082513212000447",
  1507   *      "@response_to":"IQ201608251121200",
  1508   *      "@type":"LOGIN",
  1509   *      "agent_id":{"#text":"1"},
  1510   *      "status":{"#text":"SUCCESS"},
  1511   *      "message":{"#text":"Hello Geoffrey Mina!"},
  1512   *      "detail":{"#text":"Logon request processed successfully!"},
  1513   *      "hash_code":{"#text":"404946966"},
  1514   *      "login_type":{"#text":"BLENDED"},
  1515   *      "outdial_group_id":{"#text":"50692"},
  1516   *      "skill_profile_id":{"#text":"1513"},
  1517   *      "gates":{
  1518   *          "gate_id":[
  1519   *              {"#text":"11116"},
  1520   *              {"#text":"11117"}
  1521   *          ]
  1522   *      },
  1523   *      "chat_queues":{
  1524   *          "chat_queue_id":{"#text":"30"}
  1525   *      }
  1526   *    }
  1527   * }
  1528   */
  1529  ConfigRequest.prototype.processResponse = function(response) {
  1530      var resp = response.ui_response;
  1531      var status = utils.getText(resp, "status");
  1532      var detail = utils.getText(resp, "detail");
  1533      var model = UIModel.getInstance();
  1534      var message = "";
  1535      var formattedResponse = utils.buildDefaultResponse(response);
  1536      var Lib = UIModel.getInstance().libraryInstance;
  1537      if(detail === "Logon Session Configuration Updated!"){
  1538          // this is an update login packet
  1539          model.agentSettings.updateLoginMode = true;
  1540          message = "Logon Session Configuration Updated!";
  1541          utils.logMessage(LOG_LEVELS.INFO, message, response);
  1542      }
  1543      if(status === "SUCCESS"){
  1544          if(!model.agentSettings.isLoggedIn){
  1545              // fresh login, set UI Model properties
  1546              model.configPacket = response;
  1547              model.connectionSettings.hashCode = utils.getText(resp, "hash_code");
  1548              model.agentSettings.isLoggedIn = true;
  1549              model.agentSettings.loginDTS = new Date();
  1550              model.connectionSettings.reconnect = true;
  1551              model.agentPermissions.allowLeadSearch = false;
  1552              model.agentSettings.dialDest = model.configRequest.dialDest; // not sent in response
  1553              model.agentSettings.loginType = utils.getText(resp, "login_type");
  1554              model.agentSettings.guid = utils.getText(resp,"guid");
  1555              model.agentSettings.accountId = utils.getText(resp,"account_id");
  1556              // Set collection values
  1557              setDialGroupSettings(response);
  1558              setGateSettings(response);
  1559              setChatQueueSettings(response);
  1560              setSkillProfileSettings(response);
  1561          }else{
  1562              if(model.agentSettings.updateLoginMode){
  1563                  model.agentSettings.dialDest = model.configRequest.dialDest;
  1564                  model.agentSettings.loginType = utils.getText(resp, "login_type");
  1565                  model.agentSettings.guid = utils.getText(resp,"guid");
  1566                  model.agentSettings.accountId = utils.getText(resp,"account_id");
  1567                  // This was an update login request
  1568                  model.agentSettings.updateLoginMode = false;
  1569                  // reset to false before updating dial group settings
  1570                  model.agentPermissions.allowLeadSearch = false;
  1571                  model.agentPermissions.requireFetchedLeadsCalled = false;
  1572                  model.agentPermissions.allowPreviewLeadFilters = false;
  1573                  // Set collection values
  1574                  setDialGroupSettings(response);
  1575                  setGateSettings(response);
  1576                  setChatQueueSettings(response);
  1577                  setSkillProfileSettings(response);
  1578              }else{
  1579                  // this was a reconnect
  1580                  message = "Processed a Layer 2 Reconnect Successfully";
  1581                  model.connectionSettings.isOnCall = utils.getText(resp, "is_on_call");
  1582                  model.connectionSettings.activeCallUii  =  utils.getText(resp, "active_call_uii");
  1583                  model.connectionSettings.isPendingDisp = utils.getText(resp, "is_pending_disp");
  1584                  if(model.connectionSettings.isOnCall === false){
  1585                      if(model.currentCall.uii) {
  1586                          var mockEndCallPacket = {
  1587                              "ui_notification": {
  1588                                  "@message_id": "",
  1589                                  "@type": "END-CALL",
  1590                                  "uii": {"#text": model.currentCall.uii},
  1591                                  "term_reason": {"#text": "SOCKET-DISCONNECT"}
  1592                              }
  1593                          };
  1594                          utils.processNotification(Lib, mockEndCallPacket);
  1595                      }
  1596                      if(model.agentSettings.isOffhook){
  1597                          var offHookTermPacket = {
  1598                              "ui_notification" : {
  1599                                  "agent_id" : {"#text": UIModel.getInstance().agentSettings.agentId},
  1600                                  "@type" : "OFF-HOOK-TERM",
  1601                                  "@message_id": ""
  1602                              }
  1603                          };
  1604                          var agentProcessOffhookCallback = utils.processNotification(Lib, offHookTermPacket);
  1605                          Lib.offhookTerm(agentProcessOffhookCallback);
  1606                      }
  1607                  }else if(model.connectionSettings.isOnCall && (model.currentCall.uii !== model.connectionSettings.activeCallUii || Lib.waitingForAddSession === true)){
  1608                      //if the agent does not know it is on a call, but IQ thinks it is on a call
  1609                      //normally in the case of disconnect during transition
  1610                      model.currentCall.uii = model.connectionSettings.activeCallUii;
  1611                      model.currentCall.pendingDisp = false;
  1612                      Lib.hangup(1, true);
  1613                      
  1614                  }else{
  1615                      //agent still is on call and there are transferSessions, verify no transferSession were drop
  1616                      var activeAgentUiSessions = Lib.getTransferSessions();
  1617                      var activeAgentSessions = response.ui_response.active_call_sessions.call_session_id.map(function(sessionObj){
  1618                          return sessionObj['#text'];
  1619                      });
  1620                      for(var transferSession in activeAgentUiSessions){
  1621                          if(activeAgentSessions.indexOf(transferSession) === -1){
  1622                              //if the active ui session is no longer active, we need to tell the ui
  1623                              delete UIModel.getInstance().transferSessions[transferSession];
  1624                          }
  1625                      }
  1626                  }
  1627                  utils.logMessage(LOG_LEVELS.INFO, message, response);
  1628              }
  1629          }
  1630          formattedResponse.agentSettings = model.agentSettings;
  1631          formattedResponse.agentPermissions = model.agentPermissions;
  1632          formattedResponse.applicationSettings = model.applicationSettings;
  1633          formattedResponse.chatSettings = model.chatSettings;
  1634          formattedResponse.connectionSettings = model.connectionSettings;
  1635          formattedResponse.inboundSettings = model.inboundSettings;
  1636          formattedResponse.outboundSettings = model.outboundSettings;
  1637          formattedResponse.scriptSettings = model.scriptSettings;
  1638      }else{
  1639          // Login failed
  1640          if(formattedResponse.message === ""){
  1641              formattedResponse.message = "Agent configuration attempt failed (2nd layer login)"
  1642          }
  1643          utils.logMessage(LOG_LEVELS.WARN, formattedResponse.message, response);
  1644      }
  1645      return formattedResponse;
  1646  };
  1647  function setDialGroupSettings(response){
  1648      var model = UIModel.getInstance();
  1649      var outdialGroups = model.outboundSettings.availableOutdialGroups;
  1650      model.outboundSettings.outdialGroup = {}; // reset
  1651      for(var g = 0; g < outdialGroups.length; g++){
  1652          var group = outdialGroups[g];
  1653          if(group.dialGroupId === response.ui_response.outdial_group_id['#text']){
  1654              model.agentPermissions.allowLeadSearch = group.allowLeadSearch;
  1655              model.agentPermissions.allowPreviewLeadFilters = group.allowPreviewLeadFilters;
  1656              model.agentPermissions.progressiveEnabled = group.progressiveEnabled;
  1657              model.outboundSettings.outdialGroup = JSON.parse(JSON.stringify(group)); // copy object
  1658              // Only used for Preview or TCPA Safe accounts.
  1659              // If set to true, only allow fetching new leads when current leads are called or expired
  1660              model.agentPermissions.requireFetchedLeadsCalled = group.requireFetchedLeadsCalled;
  1661          }
  1662      }
  1663  }
  1664  function setSkillProfileSettings(response){
  1665      var model = UIModel.getInstance();
  1666      model.inboundSettings.skillProfile = {};
  1667      var skillProfiles = model.inboundSettings.availableSkillProfiles;
  1668      for(var s = 0; s < skillProfiles.length; s++){
  1669          var profile = skillProfiles[s];
  1670          var responseId = utils.getText(response.ui_response, "skill_profile_id");
  1671          if(profile.profileId === responseId){
  1672              model.inboundSettings.skillProfile = JSON.parse(JSON.stringify(profile)); // copy object
  1673          }
  1674      }
  1675  }
  1676  function setGateSettings(response){
  1677      var model = UIModel.getInstance();
  1678      var gates = model.inboundSettings.availableQueues;
  1679      var selectedGateIds = [];
  1680      var selectedGates = [];
  1681      var gateIds = response.ui_response.gates.gate_id || [];
  1682      if (!Array.isArray(gateIds)) {
  1683          gateIds = [gateIds];
  1684      }
  1685      for(var s = 0; s < gateIds.length; s++){
  1686          var obj = gateIds[s];
  1687          selectedGateIds.push(obj["#text"]);
  1688      }
  1689      for(var gIdx = 0; gIdx < gates.length; gIdx++){
  1690          var gate = gates[gIdx];
  1691          if(selectedGateIds.indexOf(gate.gateId) > -1){
  1692              selectedGates.push(gate);
  1693          }
  1694      }
  1695      model.inboundSettings.queues = JSON.parse(JSON.stringify(selectedGates)); // copy array
  1696  }
  1697  function setChatQueueSettings(response){
  1698      var model = UIModel.getInstance();
  1699      var chatQueues = model.chatSettings.availableChatQueues;
  1700      var selectedChatQueueIds = [];
  1701      var selectedChatQueues = [];
  1702      var cQueues = response.ui_response.chat_queues || {};
  1703      var chatQueueIds = cQueues.chat_queue_id || [];
  1704      if (!Array.isArray(chatQueueIds)) {
  1705          chatQueueIds = [chatQueueIds];
  1706      }
  1707      for(var c = 0; c < chatQueueIds.length; c++){
  1708          var obj = chatQueueIds[c];
  1709          selectedChatQueueIds.push(obj["#text"]);
  1710      }
  1711      for(var cIdx = 0; cIdx < chatQueues.length; cIdx++){
  1712          var chatQueue = chatQueues[cIdx];
  1713          if(selectedChatQueueIds.indexOf(chatQueue.chatQueueId) > -1){
  1714              selectedChatQueues.push(chatQueue);
  1715          }
  1716      }
  1717      model.chatSettings.chatQueues = JSON.parse(JSON.stringify(selectedChatQueues)); // copy array
  1718  }
  1719  var DirectAgentTransfer = function(targetAgentId, transferType, uii) {
  1720      this.targetAgentId = targetAgentId;
  1721      this.transferType = transferType;
  1722      this.uii = uii || UIModel.getInstance().currentCall.uii;
  1723  };
  1724  DirectAgentTransfer.prototype.formatJSON = function() {
  1725      var model = UIModel.getInstance();
  1726      var msg = {
  1727          "ui_request": {
  1728              "@destination": "IQ",
  1729              "@type": MESSAGE_TYPES.DIRECT_AGENT_TRANSFER,
  1730              "@message_id": utils.getMessageId(),
  1731              "@response_to": "",
  1732              "agent_id":{
  1733                  "#text": utils.toString(model.agentSettings.agentId)
  1734              },
  1735              "uii": {
  1736                  "#text": utils.toString(this.uii)
  1737              },
  1738              "target_agent_id": {
  1739                  "#text": utils.toString(this.targetAgentId)
  1740              },
  1741              "transfer_type": {
  1742                  "#text": utils.toString(this.transferType)
  1743              }
  1744          }
  1745      };
  1746      return JSON.stringify(msg);
  1747  };
  1748  /*
  1749   * This class processes DIRECT-AGENT-TRANSFER packets rec'd from IQ.
  1750   *
  1751   * {"ui_response":{
  1752   *      "@message_id":"IQ10012016082314475000219",
  1753   *      "@response_to":"",
  1754   *      "@type":"DIRECT-AGENT-TRANSFER",
  1755   *      "status":{"#text":"OK"},
  1756   *      "message":{"#text":"OK"},
  1757   *      "type":{"#text":"WARM|COLD|CANCEL"}
  1758   *   }
  1759   * }
  1760   */
  1761  DirectAgentTransfer.prototype.processResponse = function(response) {
  1762      var resp = response.ui_response;
  1763      var formattedResponse = utils.buildDefaultResponse(response);
  1764      formattedResponse.type = utils.getText(resp, 'type');
  1765      if(formattedResponse.status !== "OK"){
  1766          // log message response
  1767          var message = "There was an error processing the Direct Agent Transfer request. " + formattedResponse.message + " : " + formattedResponse.detail;
  1768          utils.logMessage(LOG_LEVELS.WARN, message, response);
  1769      }
  1770      return formattedResponse;
  1771  };
  1772  var DirectAgentTransferList = function() { };
  1773  DirectAgentTransferList.prototype.formatJSON = function() {
  1774      var msg = {
  1775          "ui_request": {
  1776              "@destination": "IQ",
  1777              "@type": MESSAGE_TYPES.DIRECT_AGENT_TRANSFER_LIST,
  1778              "@message_id": utils.getMessageId(),
  1779              "@response_to": "",
  1780              "agent_id":{
  1781                  "#text": UIModel.getInstance().agentSettings.agentId
  1782              }
  1783          }
  1784      };
  1785      return JSON.stringify(msg);
  1786  };
  1787  /*
  1788   * This class processes DIRECT-AGENT-TRANSFER-LIST packets rec'd from IQ.
  1789   *
  1790   *  {
  1791   *      "ui_response":{
  1792   *          "@message_id":"IQD01DEV2018052917202600038",
  1793   *          "@response_to":"f0b2e8a3-87fe-13ee-4d00-9d145bfe2be8",
  1794   *          "@type":"DIRECT-AGENT-TRANSFER-LIST",
  1795   *          "status":{
  1796   *              "#text":"true"
  1797   *          },
  1798   *          "message":{
  1799   *              "#text":"OK"
  1800   *          },
  1801   *          "agents": [
  1802   *             {
  1803   *                 "@agent_aux_state":"AVAILABLE",
  1804   *                 "@agent_id":"1184160",
  1805   *                 "@agent_state":"AVAILABLE",
  1806   *                 "@available":"true",
  1807   *                 "@first_name":"ross",
  1808   *                 "@last_name":"m",
  1809   *                 "@pending_disp":"false",
  1810   *                 "@state_duration":"379",
  1811   *                 "@username":"rm1"
  1812   *             },
  1813   *             {
  1814   *                 "@agent_aux_state":"AVAILABLE",
  1815   *                 "@agent_id":"1184161",
  1816   *                 "@agent_state":"AVAILABLE",
  1817   *                 "@available":"true",
  1818   *                 "@first_name":"ross",
  1819   *                 "@last_name":"m",
  1820   *                 "@pending_disp":"false",
  1821   *                 "@state_duration":"84",
  1822   *                 "@username":"rm2"
  1823   *             }
  1824   *         ]
  1825   *      }
  1826   *  }
  1827   */
  1828  DirectAgentTransferList.prototype.processResponse = function(response) {
  1829      var formattedResponse = utils.buildDefaultResponse(response);
  1830      formattedResponse.agents = utils.processResponseCollection(response, 'ui_response', 'agents');
  1831      if(formattedResponse.status !== "OK"){
  1832          // log message response
  1833          var message = "There was an error processing the Direct Agent Transfer List request. " + formattedResponse.message + " : " + formattedResponse.detail;
  1834          utils.logMessage(LOG_LEVELS.WARN, message, response);
  1835      }
  1836      return formattedResponse;
  1837  };
  1838  var DispositionRequest = function(uii, dispId, notes, callback, callbackDTS, contactForwardNumber, survey, externId, leadId, requestId) {
  1839      this.uii = uii;
  1840      this.dispId = dispId;
  1841      this.notes = notes;
  1842      this.callback = callback;
  1843      this.callbackDTS = callbackDTS || "";
  1844      this.contactForwardNumber = contactForwardNumber || null;
  1845      this.externId = externId || null;   // outbound-disposition only
  1846      this.leadId = leadId || null;       // outbound-disposition only
  1847      this.requestId = requestId || null; // outbound-disposition only (pipe leads)
  1848      /*
  1849       * survey = {
  1850       *      first_name: {
  1851       *          leadField: "first_name"
  1852       *          value: "Geoff"
  1853       *      },
  1854       *      last_name: {
  1855       *          leadField: "last_name"
  1856       *          value: "Mina"
  1857       *      }
  1858       *      ...
  1859       * }
  1860       */
  1861      this.survey = survey || null;
  1862  };
  1863  /*
  1864   * This class is responsible for creating an inbound or outbound disposition packet to
  1865   * send to intelliqueue. It will grab uii and agent_id directly from packets saved
  1866   * in the UIModel. Then, using the information passed in, it will
  1867   * create the remainder of the packet. This class is called from the ExtendedCallForm
  1868   *
  1869   * {"ui_request":{
  1870   *      "@message_id":"IQ20160817145840132",
  1871   *      "@response_to":"",
  1872   *      "@type":"OUTDIAL-DISPOSITION|INBOUND-DISPOSITION",
  1873   *      "session_id":{"#text":"2"},  <-- ONLY WHEN AVAILABLE otherwise the node is left blank. this is the AGENT session_id
  1874   *      "uii":{"#text":"201608171658440139000000000165"},
  1875   *      "agent_id":{"#text":"1180958"},
  1876   *      "lead_id":{"#text":"1800"},                 <-- OUTDIAL-DISPOSITION ONLY
  1877   *      "outbound_externid":{"#text":"3038593775"}, <-- OUTDIAL-DISPOSITION ONLY
  1878   *      "pending_request_id":{"#text":""},          <-- OUTDIAL-DISPOSITION ONLY
  1879   *      "disposition_id":{"#text":"5950"},
  1880   *      "notes":{"#text":"note here"},
  1881   *      "call_back":{"#text":"FALSE"},
  1882   *      "call_back_DTS":{},
  1883   *      "contact_forwarding":{},
  1884   *      "survey":{
  1885   *          "response":[
  1886   *              {"@extern_id":"text_box","@lead_update_column":"","#text":"hello"},
  1887   *              {"@extern_id":"check_box","@lead_update_column":"","#text":"20"},
  1888   *              {"@extern_id":"radio_save","@lead_update_column":"","#text":"23"}
  1889   *          ]
  1890   *      }
  1891   *   }
  1892   * }
  1893   */
  1894  DispositionRequest.prototype.formatJSON = function() {
  1895      var model = UIModel.getInstance();
  1896      var msg = {
  1897          "ui_request": {
  1898              "@destination":"IQ",
  1899              "@message_id":utils.getMessageId(),
  1900              "@response_to":"",
  1901              "@type":MESSAGE_TYPES.OUTDIAL_DISPOSITION,
  1902              "agent_id": {
  1903                  "#text" : utils.toString(model.agentSettings.agentId)
  1904              },
  1905              "session_id":{
  1906                  "#text": ""
  1907              },
  1908              "uii": {
  1909                  "#text" : utils.toString(this.uii)
  1910              },
  1911              "disposition_id": {
  1912                  "#text" : utils.toString(this.dispId)
  1913              },
  1914              "notes": {
  1915                  "#text" : utils.toString(this.notes)
  1916              },
  1917              "call_back": {
  1918                  "#text" : this.callback === true? "TRUE" : "FALSE"
  1919              },
  1920              "call_back_DTS": {
  1921                  "#text" : utils.toString(this.callbackDTS)
  1922              },
  1923              "contact_forwarding": {
  1924                  "#text" : utils.toString(this.contactForwardNumber)
  1925              },
  1926              "outbound_externid": {
  1927                  "#text" : utils.toString(this.externId)
  1928              },
  1929              "lead_id": {
  1930                  "#text" : utils.toString(this.leadId)
  1931              },
  1932              "pending_request_id": {
  1933                  "#text" : utils.toString(this.requestId)
  1934              }
  1935          }
  1936      };
  1937      if(model.currentCall.outdialDispositions && model.currentCall.outdialDispositions.type === "GATE") {
  1938          msg.ui_request['@type'] = MESSAGE_TYPES.INBOUND_DISPOSITION;
  1939      }
  1940      if(model.currentCall.sessionId){
  1941          msg.ui_request.session_id = {"#text":model.currentCall.sessionId};
  1942      }
  1943      /*
  1944       * converts survey to this response
  1945       * survey : {
  1946       *      response: [
  1947       *          { "@extern_id":"", "@lead_update_column":"", "#text":"" }
  1948       *      ]
  1949       * }
  1950       */
  1951      if(this.survey !== null){
  1952          var response = [];
  1953          var keys = Object.keys(this.survey);
  1954          for(var i = 0; i < keys.length; i++){
  1955              var key = keys[i];
  1956              var obj = {
  1957                  "@extern_id": key,
  1958                  "@lead_update_column": utils.toString(this.survey[key].leadField),
  1959                  "#text": utils.toString(this.survey[key].value)
  1960              };
  1961              response.push(obj);
  1962          }
  1963          msg.ui_request.survey = {"response":response};
  1964      }
  1965      return JSON.stringify(msg);
  1966  };
  1967  var DispositionManualPassRequest = function(dispId, notes, callback, callbackDTS, leadId, requestId, externId) {
  1968      this.dispId = dispId;
  1969      this.notes = notes;
  1970      this.callback = callback;
  1971      this.callbackDTS = callbackDTS || "";
  1972      this.leadId = leadId || null;
  1973      this.requestId = requestId || null;
  1974      this.externId = externId || null;
  1975  };
  1976  /*
  1977   * Sends an OUTDIAL-DISPOSITION request, just a separate class
  1978   * specifically for dispositions on manual pass.
  1979   *
  1980   * {"ui_request":{
  1981   *      "@message_id":"UIV220089241119416",
  1982   *      "@response_to":"",
  1983   *      "@type":"OUTDIAL-DISPOSITION",
  1984   *      "manual_disp":{"#text":"TRUE"},
  1985   *      "request_key":{"#text":"IQ10012016081719070100875"},
  1986   *      "session_id":{},
  1987   *      "uii":{},
  1988   *      "agent_id":{"#text":"1810"},
  1989   *      "lead_id":{"#text":"213215"},
  1990   *      "outbound_externid":{"#text":"909809"},
  1991   *      "disposition_id":{"#text":"126"},
  1992   *      "notes":{"#text":"here are my notes :)"},
  1993   *      "call_back":{"#text":"TRUE | FALSE"},
  1994   *      "call_back_DTS":{"#text":"2008-09-30 22:30:00 | null"},
  1995   *      "contact_forwarding":{"#text":"null"}
  1996   *    }
  1997   * }
  1998   */
  1999  DispositionManualPassRequest.prototype.formatJSON = function() {
  2000      var model = UIModel.getInstance();
  2001      var msg = {
  2002          "ui_request": {
  2003              "@destination":"IQ",
  2004              "@message_id":utils.getMessageId(),
  2005              "@response_to":"",
  2006              "@type":MESSAGE_TYPES.OUTDIAL_DISPOSITION,
  2007              "manual_disp": {
  2008                  "#text" : "TRUE"
  2009              },
  2010              "agent_id": {
  2011                  "#text" : utils.toString(model.agentSettings.agentId)
  2012              },
  2013              "request_key": {
  2014                  "#text": utils.toString(this.requestId)
  2015              },
  2016              "disposition_id": {
  2017                  "#text" : utils.toString(this.dispId)
  2018              },
  2019              "notes": {
  2020                  "#text" : utils.toString(this.notes)
  2021              },
  2022              "call_back": {
  2023                  "#text" : this.callback === true? "TRUE" : "FALSE"
  2024              },
  2025              "call_back_DTS": {
  2026                  "#text" : utils.toString(this.callbackDTS)
  2027              },
  2028              "lead_id": {
  2029                  "#text" : utils.toString(this.leadId)
  2030              },
  2031              "extern_id": {
  2032                  "#text" : utils.toString(this.externId)
  2033              },
  2034              "contact_forwarding": {
  2035                  "#text": "null"
  2036              },
  2037              "session_id":{},
  2038              "uii": {}
  2039          }
  2040      };
  2041      return JSON.stringify(msg);
  2042  };
  2043  var HangupRequest = function(sessionId, resetPendingDisp) {
  2044      this.sessionId = sessionId || null;
  2045      this.resetPendingDisp = resetPendingDisp || false;
  2046  };
  2047  HangupRequest.prototype.formatJSON = function() {
  2048      var msg = {
  2049          "ui_request": {
  2050              "@destination":"IQ",
  2051              "@type":MESSAGE_TYPES.HANGUP,
  2052              "@message_id":utils.getMessageId(),
  2053              "response_to":"",
  2054              "agent_id":{
  2055                  "#text":utils.toString(UIModel.getInstance().agentSettings.agentId)
  2056              },
  2057              "uii":{
  2058                  "#text":utils.toString(UIModel.getInstance().currentCall.uii)
  2059              },
  2060              "session_id":{
  2061                  "#text":utils.toString(this.sessionId === null ? UIModel.getInstance().currentCall.sessionId : this.sessionId)
  2062              },
  2063              "cancel_pending_disp" : {
  2064                  "#text" : this.resetPendingDisp === true ? "TRUE" : "FALSE"
  2065              }
  2066          }
  2067      };
  2068      return JSON.stringify(msg);
  2069  };
  2070  var HoldRequest = function(holdState, sessionId) {
  2071      this.holdState = holdState;
  2072      this.sessionId = sessionId || '1';
  2073  };
  2074  /*
  2075   * {"ui_request":{
  2076   *      "@destination":"IQ",
  2077   *      "@message_id":"UI200809291036128",
  2078   *      "@response_to":"",
  2079   *      "@type":"HOLD",
  2080   *      "agent_id":{"#text":"1856"},
  2081   *      "uii":{"#text":"200808291035510000000900029412"},
  2082   *      "session_id":{"#text":"1"},
  2083   *      "hold_state":{"#text":"ON"}
  2084   *    }
  2085   * }
  2086   */
  2087  HoldRequest.prototype.formatJSON = function() {
  2088      var model = UIModel.getInstance();
  2089      var msg = {
  2090          "ui_request": {
  2091              "@destination":"IQ",
  2092              "@type":MESSAGE_TYPES.HOLD,
  2093              "@message_id":utils.getMessageId(),
  2094              "@response_to":"",
  2095              "agent_id":{
  2096                  "#text":utils.toString(model.currentCall.agentId)
  2097              },
  2098              "uii":{
  2099                  "#text":utils.toString(model.currentCall.uii)
  2100              },
  2101              "session_id":{
  2102                  "#text": utils.toString(this.sessionId)
  2103              },
  2104              "hold_state":{
  2105                  "#text":this.holdState === true || this.holdState === "true" ? "ON" : "OFF"
  2106              }
  2107          }
  2108      };
  2109      return JSON.stringify(msg);
  2110  };
  2111  /*
  2112   * This class processes HOLD packets rec'd from IQ.
  2113   *
  2114   * {"ui_response":{
  2115   *      "@message_id":"IQ982008082910361503344",
  2116   *      "@response_to":"",
  2117   *      "@type":"HOLD",
  2118   *      "uii":{"#text":"200808291035510000000900029412"},
  2119   *      "session_id":{"#text":"1"},
  2120   *      "status":{"#text":"OK"},
  2121   *      "message":{},
  2122   *      "detail":{},
  2123   *      "hold_state":{"#text":"ON"}
  2124   *    }
  2125   * }
  2126   */
  2127  HoldRequest.prototype.processResponse = function(response) {
  2128      var resp = response.ui_response;
  2129      var formattedResponse = utils.buildDefaultResponse(response);
  2130      var currUII = "";
  2131      if(UIModel.getInstance().currentCall.uii){
  2132         currUII = UIModel.getInstance().currentCall.uii;
  2133      }
  2134      formattedResponse.holdState = utils.getText(resp, 'hold_state') === "ON";
  2135      formattedResponse.sessionId = utils.getText(resp, 'session_id');
  2136      formattedResponse.uii = utils.getText(resp, 'uii');
  2137      if(formattedResponse.status === "OK"){
  2138          // make sure we are talking about the same call
  2139          if(formattedResponse.uii === currUII){
  2140              if(formattedResponse.message === ""){
  2141                  formattedResponse.message = "Broadcasting new hold state of " + formattedResponse.holdState;
  2142              }
  2143              utils.logMessage(LOG_LEVELS.DEBUG, "Broadcasting new hold state of " + formattedResponse.holdState, response);
  2144          }
  2145          else{
  2146              utils.logMessage(LOG_LEVELS.DEBUG, "Hold Response is for a different call...discarding", response);
  2147          }
  2148      }else{
  2149          if(formattedResponse.message === ""){
  2150              formattedResponse.message = "Error processing HOLD request. " +  + formattedResponse.message + "\n" + formattedResponse.detail;
  2151          }
  2152          utils.logMessage(LOG_LEVELS.WARN, "Error processing HOLD request. " + formattedResponse.detail, response);
  2153      }
  2154      var model = UIModel.getInstance();
  2155      if(formattedResponse.sessionId !== '1' && model.transferSessions[formattedResponse.sessionId]) {
  2156          // we have a hold for a transfer session
  2157          model.transferSessions[formattedResponse.sessionId].onHold = formattedResponse.holdState;
  2158      }
  2159      return formattedResponse;
  2160  };
  2161  var LeadHistoryRequest = function(leadId) {
  2162      this.leadId = leadId;
  2163  };
  2164  /*
  2165   * {"ui_request":{
  2166   *      "@destination":"IQ",
  2167   *      "@message_id":"UI200809291036128",
  2168   *      "@response_to":"",
  2169   *      "@type":"LEAD-HISTORY",
  2170   *      "agent_id":{"#text":"1"},
  2171   *      "lead_id":{"#text":"12"},
  2172   *    }
  2173   * }
  2174   */
  2175  LeadHistoryRequest.prototype.formatJSON = function() {
  2176      var model = UIModel.getInstance();
  2177      var msg = {
  2178          "ui_request": {
  2179              "@destination":"IQ",
  2180              "@type":MESSAGE_TYPES.LEAD_HISTORY,
  2181              "@message_id":utils.getMessageId(),
  2182              "@response_to":"",
  2183              "agent_id":{
  2184                  "#text":utils.toString(model.agentSettings.agentId)
  2185              },
  2186              "lead_id":{
  2187                  "#text":utils.toString(this.leadId)
  2188              }
  2189          }
  2190      };
  2191      return JSON.stringify(msg);
  2192  };
  2193  /*
  2194   * This class processes LEAD-HISTORY packets rec'd from IQ.
  2195   *
  2196   * {"ui_response":{
  2197   *      "@lead_id":"2653",
  2198   *      "@message_id":"IQ982008091512353000875",
  2199   *      "@response_to":"UIV220089151235539",
  2200   *      "@type":"LEAD-HISTORY",
  2201   *      "previous_dial":{
  2202   *          "@agent_name":"mandy pants (mandy)",
  2203   *          "@duration":"",
  2204   *          "@pass_disposition":"",
  2205   *          "@pass_dts":"2008-09-15 12:35:27",
  2206   *          "@pass_number":"",
  2207   *          "@pass_uii":"200809151234140000000900021288",
  2208   *          "agent_notes":{"#text":"This person was incredibly nice and agreed to buy donuts. "},
  2209   *          "agent_disposition":{"#text":"Incomplete"}
  2210   *      }
  2211   *   }
  2212   * }
  2213   *
  2214   * OR
  2215   *
  2216   * {"ui_response":{
  2217   *      "@lead_id":"2653",
  2218   *      "@message_id":"IQ982008091512353000875",
  2219   *      "@response_to":"UIV220089151235539",
  2220   *      "@type":"LEAD-HISTORY",
  2221   *      "previous_dial":[
  2222   *        {
  2223   *          "@agent_name":"mandy pants (mandy)",
  2224   *          "@duration":"",
  2225   *          "@pass_disposition":"",
  2226   *          "@pass_dts":"2008-09-15 12:35:27",
  2227   *          "@pass_number":"",
  2228   *          "@pass_uii":"200809151234140000000900021288",
  2229   *          "agent_notes":{"#text":"This person was incredibly nice and agreed to buy donuts. "},
  2230   *          "agent_disposition":{"#text":"Incomplete"}
  2231   *        },
  2232   *        {
  2233   *          "@agent_name":"mandy pants (mandy)",
  2234   *          "@duration":"",
  2235   *          "@pass_disposition":"",
  2236   *          "@pass_dts":"2008-09-15 12:35:27",
  2237   *          "@pass_number":"",
  2238   *          "@pass_uii":"200809151234140000000900021288",
  2239   *          "agent_notes":{"#text":"This person was incredibly nice and agreed to buy donuts. "},
  2240   *          "agent_disposition":{"#text":"Incomplete"}
  2241   *        }
  2242   *      ]
  2243   *   }
  2244   * }
  2245   */
  2246  LeadHistoryRequest.prototype.processResponse = function(response) {
  2247      var resp = response.ui_response;
  2248      var histResponse = {
  2249          leadId: resp['@lead_id']
  2250      };
  2251      var history = utils.processResponseCollection(response, 'ui_response', 'previous_dial');
  2252      // always return array, even if only one item
  2253      if(!Array.isArray(history)){
  2254          history = [history];
  2255      }
  2256      histResponse.leadHistory = history;
  2257      return histResponse;
  2258  };
  2259  var LeadInsertRequest = function(dataObj) {
  2260      // handle boolean value conversion
  2261      if(dataObj.agent_reserved && dataObj.agent_reserved === true){
  2262          dataObj.agent_reserved = "1";
  2263      }else{
  2264          dataObj.agent_reserved = "0";
  2265      }
  2266      if(dataObj.dialable && dataObj.dialable === true){
  2267          dataObj.dialable = "1";
  2268      }else{
  2269          dataObj.dialable = "0";
  2270      }
  2271      this.dataObj = dataObj;
  2272  };
  2273  /*
  2274   * {"ui_request":{
  2275   *      "@destination":"IQ",
  2276   *      "@message_id":"UI200809291036128",
  2277   *      "@response_to":"",
  2278   *      "@type":"LEAD-INSERT",
  2279   *      "agent_id":{"#text":"1"},
  2280   *      "campaign_id":{"#text":""},
  2281   *      "lead_phone":{"#text":""},
  2282   *      "dialable":{"#text":""},
  2283   *      "agent_reserved":{"#text":""},
  2284   *      "callback_dts":{"#text":""},
  2285   *      "first_name":{"#text":""},
  2286   *      "mid_name":{"#text":""},
  2287   *      "last_name":{"#text":""},
  2288   *      "suffix":{"#text":""},
  2289   *      "title":{"#text":""},
  2290   *      "address1":{"#text":""},
  2291   *      "address2":{"#text":""},
  2292   *      "city":{"#text":""},
  2293   *      "state":{"#text":""},
  2294   *      "zip":{"#text":""},
  2295   *      "email":{"#text":""},
  2296   *      "gateKeeper":{"#text":""},
  2297   *      "aux_data1":{"#text":""},
  2298   *      "aux_data2":{"#text":""},
  2299   *      "aux_data3":{"#text":""},
  2300   *      "aux_data4":{"#text":""},
  2301   *      "aux_data5":{"#text":""},
  2302   *    }
  2303   * }
  2304   */
  2305  LeadInsertRequest.prototype.formatJSON = function() {
  2306      var model = UIModel.getInstance();
  2307      var msg = {
  2308          "ui_request": {
  2309              "@destination":"IQ",
  2310              "@type":MESSAGE_TYPES.LEAD_INSERT,
  2311              "@message_id":utils.getMessageId(),
  2312              "@response_to":"",
  2313              "agent_id":{
  2314                  "#text":utils.toString(this.dataObj.agent_id)
  2315              },
  2316              "campaign_id":{
  2317                  "#text":utils.toString(this.dataObj.campaign_id)
  2318              },
  2319              "lead_phone":{
  2320                  "#text":utils.toString(this.dataObj.lead_phone)
  2321              },
  2322              "dialable":{
  2323                  "#text":utils.toString(this.dataObj.dialable)
  2324              },
  2325              "agent_reserved":{
  2326                  "#text":utils.toString(this.dataObj.agent_reserved)
  2327              },
  2328              "call_back_dts":{
  2329                  "#text":utils.toString(this.dataObj.callback_dts)
  2330              },
  2331              "first_name":{
  2332                  "#text":utils.toString(this.dataObj.first_name)
  2333              },
  2334              "mid_name":{
  2335                  "#text":utils.toString(this.dataObj.mid_name)
  2336              },
  2337              "last_name":{
  2338                  "#text":utils.toString(this.dataObj.last_name)
  2339              },
  2340              "suffix":{
  2341                  "#text":utils.toString(this.dataObj.suffix)
  2342              },
  2343              "title":{
  2344                  "#text":utils.toString(this.dataObj.title)
  2345              },
  2346              "address1":{
  2347                  "#text":utils.toString(this.dataObj.address1)
  2348              },
  2349              "address2":{
  2350                  "#text":utils.toString(this.dataObj.address2)
  2351              },
  2352              "city":{
  2353                  "#text":utils.toString(this.dataObj.city)
  2354              },
  2355              "state":{
  2356                  "#text":utils.toString(this.dataObj.state)
  2357              },
  2358              "zip":{
  2359                  "#text":utils.toString(this.dataObj.zip)
  2360              },
  2361              "email":{
  2362                  "#text":utils.toString(this.dataObj.email)
  2363              },
  2364              "gate_keeper":{
  2365                  "#text":utils.toString(this.dataObj.gate_keeper)
  2366              },
  2367              "aux_data1":{
  2368                  "#text":utils.toString(this.dataObj.aux_data1)
  2369              },
  2370              "aux_data2":{
  2371                  "#text":utils.toString(this.dataObj.aux_data2)
  2372              },
  2373              "aux_data3":{
  2374                  "#text":utils.toString(this.dataObj.aux_data3)
  2375              },
  2376              "aux_data4":{
  2377                  "#text":utils.toString(this.dataObj.aux_data4)
  2378              },
  2379              "aux_data5":{
  2380                  "#text":utils.toString(this.dataObj.aux_data5)
  2381              }
  2382          }
  2383      };
  2384      return JSON.stringify(msg);
  2385  };
  2386  /*
  2387   * This class processes LEAD-INSERT packets rec'd from IQ.
  2388   *
  2389   * {"ui_response":{
  2390   *      "@message_id":"IQ982008091512353000875",
  2391   *      "@response_to":"UIV220089151235539",
  2392   *      "@type":"LEAD-INSERT",
  2393   *      "status":{"#text":"TRUE|FALSE"},
  2394   *      "msg":{"#text":""},
  2395   *      "detail":{"#text":""},
  2396   *   }
  2397   * }
  2398   */
  2399  LeadInsertRequest.prototype.processResponse = function(response) {
  2400      var resp = response.ui_response;
  2401      var formattedResponse = utils.buildDefaultResponse(response);
  2402      formattedResponse.message = resp.msg["#text"];
  2403      return formattedResponse;
  2404  };
  2405  var LeadUpdateRequest = function(leadId, leadPhone, baggage) {
  2406      this.leadId = leadId;
  2407      this.leadPhone = leadPhone;
  2408      this.baggage = baggage;
  2409      this.agentId = utils.toString(UIModel.getInstance().agentSettings.agentId);
  2410  };
  2411  /*
  2412   * {"ui_request":{
  2413   *      "@destination":"IQ",
  2414   *      "@message_id":"UI200809291036128",
  2415   *      "@response_to":"",
  2416   *      "@type":"LEAD-UPDATE",
  2417   *      "agent_id":{"#text":"1"},
  2418   *      "lead_id":{"#text":"12"},
  2419   *      "lead_phone":{"#text":"12"},
  2420   *       "baggage":{
  2421   *          "lead_id":{"#text":"64306"},
  2422   *          "extern_id":{"#text":"9548298548"},
  2423   *          "first_name":{"#text":"Ryant"},
  2424   *          "mid_name":{},
  2425   *          "last_name":{"#text":"Taylor"},
  2426   *          "state":{"#text":"OH"},
  2427   *          "aux_data1":{"#text":"BMAK"},
  2428   *          "aux_data2":{"#text":"BMAK-041653-934"},
  2429   *          "aux_data3":{"#text":"Call Ctr 1"},
  2430   *          "aux_data4":{},
  2431   *          "aux_data5":{},
  2432   *          "address1":{"#text":"8010 Maryland Ave"},
  2433   *          "address2":{},
  2434   *          "city":{"#text":"Cleveland"},
  2435   *          "zip":{"#text":"44105"},
  2436   *          "aux_external_url":{},
  2437   *          "aux_greeting":{},
  2438   *          "aux_phone":{}
  2439   *      },
  2440   *    }
  2441   * }
  2442   */
  2443  LeadUpdateRequest.prototype.formatJSON = function() {
  2444      // make sure required baggage fields are present
  2445      this.baggage = _formatBaggage(this.baggage);
  2446      var msg = {
  2447          "ui_request": {
  2448              "@destination":"IQ",
  2449              "@type":MESSAGE_TYPES.LEAD_UPDATE,
  2450              "@message_id":utils.getMessageId(),
  2451              "@response_to":"",
  2452              "agent_id":{
  2453                  "#text":this.agentId
  2454              },
  2455              "lead_id":{
  2456                  "#text":utils.toString(this.leadId)
  2457              },
  2458              "lead_phone":{
  2459                  "#text":utils.toString(this.leadPhone)
  2460              },
  2461              "baggage": this.baggage
  2462          }
  2463      };
  2464      return JSON.stringify(msg);
  2465  };
  2466  /*
  2467   * This class processes LEAD-UPDATE packets rec'd from IQ.
  2468   *
  2469   * {"ui_response":{
  2470   *      "@message_id":"IQ982008091512353000875",
  2471   *      "@response_to":"UIV220089151235539",
  2472   *      "@type":"LEAD-UPDATE",
  2473   *      "status":{"#text":"TRUE|FALSE"},
  2474   *      "msg":{"#text":"64306"},
  2475   *      "detail":{"#text":"64306"},
  2476   *   }
  2477   * }
  2478   */
  2479  LeadUpdateRequest.prototype.processResponse = function(response) {
  2480      var resp = response.ui_response;
  2481      var formattedResponse = utils.buildDefaultResponse(response);
  2482      formattedResponse.message = resp.msg["#text"];
  2483      return formattedResponse;
  2484  };
  2485  _formatBaggage = function(baggage){
  2486      var bag = {};
  2487      bag.first_name = {"#text": baggage.first_name || ""};
  2488      bag.mid_name = {"#text":baggage.mid_name || ""};
  2489      bag.last_name = {"#text":baggage.last_name || ""};
  2490      bag.suffix =  {"#text":baggage.suffix || ""};
  2491      bag.title = {"#text":baggage.title || ""};
  2492      bag.address1 = {"#text":baggage.address1 || ""};
  2493      bag.address2 = {"#text":baggage.address2 || ""};
  2494      bag.city = {"#text":baggage.city || ""};
  2495      bag.state = {"#text":baggage.state || ""};
  2496      bag.zip = {"#text":baggage.zip || ""};
  2497      bag.email = {"#text":baggage.email || ""};
  2498      bag.gate_keeper = {"#text":baggage.gate_keeper || ""};
  2499      bag.extern_id = {"#text":baggage.extern_id || ""};
  2500      bag.aux_data1 = {"#text":baggage.aux_data1 || ""};
  2501      bag.aux_data2 = {"#text":baggage.aux_data2 || ""};
  2502      bag.aux_data3 = {"#text":baggage.aux_data3 || ""};
  2503      bag.aux_data4 = {"#text":baggage.aux_data4 || ""};
  2504      bag.aux_data5 = {"#text":baggage.aux_data5 || ""};
  2505      return bag;
  2506  };
  2507  var LoginRequest = function(username, password, isCaseSensitive) {
  2508      this.username = username;
  2509      this.password = password;
  2510      this.isCaseSensitive = isCaseSensitive || false;
  2511  };
  2512  LoginRequest.prototype.formatJSON = function() {
  2513      var msg = {
  2514          "ui_request": {
  2515              "@destination":"IS",
  2516              "@type":MESSAGE_TYPES.LOGIN,
  2517              "@message_id":utils.getMessageId(),
  2518              "response_to":"",
  2519              "username":{
  2520                  "#text":this.username
  2521              },
  2522              "password":{
  2523                  "#text":this.password
  2524              },
  2525              "is_case_sensitive":{
  2526                  "#text":utils.toString(this.isCaseSensitive === true ? "TRUE" : "FALSE")
  2527              }
  2528          }
  2529      };
  2530      return JSON.stringify(msg);
  2531  };
  2532  /*
  2533   * This function is responsible for handling the login packet received from IntelliServices. It will save
  2534   * a copy of it in the UIModel as loginPacket, as well as set the isLoggedInIS variable to
  2535   * true (for reconnect purposes) and the loginDTS with the current date/time.
  2536   *
  2537   * {"ui_response":{
  2538   *      "@type":"login",
  2539   *      "status":{"#text":"OK"},
  2540   *      "agent_id":{"#text":"1810"},
  2541   *      "agent_pwd":{"#text":"bound25"},
  2542   *      "first_name":{"#text":"mandy"},
  2543   *      "last_name":{"#text":"pants"},
  2544   *      "email":{"#text":"mandypants@aol.coim"},
  2545   *      "agent_type":{"#text":"AGENT"},
  2546   *      "external_agent_id":{"#text":"blahblah"},
  2547   *      "default_login_dest":{"#text":"9548298548|123"},
  2548   *      "alt_default_login_dest":{"#text":"9548298548|123"},
  2549   *      "iq_url":{"#text":"dev.connectfirst.com"},
  2550   *      "iq_port":{"#text":"1313"},
  2551   *      "iq_ssl_port":{"#text":"1213"},
  2552   *      "iq_secret_key":{"#text":"F-OFF"},
  2553   *      "allow_inbound":{"#text":"1"},
  2554   *      "allow_outbound":{"#text":"1"},
  2555   *      "allow_chat":{"#text":"1"},
  2556   *      "allow_blended":{"#text":"0"},
  2557   *      "allow_off_hook":{"#text":"1"},
  2558   *      "allow_call_control":{"#text":"1"},
  2559   *      "allow_login_control":{"#text":"1"},
  2560   *      "allow_login_updates":{"#text":"1"},
  2561   *      "allow_lead_inserts":{"#text":"1"},
  2562   *      "show_lead_history":{"#text":"1"},
  2563   *      "allow_cross_gate_requeue":{"#text":"1"},
  2564   *      "phone_login_dial_group":{"#text":"44"},
  2565   *      "phone_login_pin":{"#text":"1234"},
  2566   *      "allow_manual_calls":{"#text":"1"},
  2567   *      "allow_manual_intl_calls":{"#text":"0"},
  2568   *      "init_login_state":{"#text":"ON-BREAK"},
  2569   *      "init_login_state_label":{"#text":"Morning Break"},
  2570   *      "outbound_prepay":{"#text":"0"},
  2571   *      "max_break_time":{"#text":"-1"},
  2572   *      "max_lunch_time":{"#text":"-1"},
  2573   *      "allow_lead_search":{"#text":"YES_ALL"},
  2574   *      "tcpa_safe_mode":{"#text":"1|0"},
  2575   *      "pci_enabled":{"#text":"1|0"},
  2576   *      "login_gates":{
  2577   *          "gate":[
  2578   *              {"@default_dest_override":"","@gate_desc":"","@gate_id":"37","@gate_name":"test"},
  2579   *              {"@default_dest_override":"","@gate_desc":"","@gate_id":"42","@gate_name":"test gate two"},
  2580   *              {"@default_dest_override":"","@gate_desc":"","@gate_id":"43","@gate_name":"test gate three"},
  2581   *              {"@default_dest_override":"","@gate_desc":"Amandas Other Gate","@gate_id":"46","@gate_name":"You know it!"}
  2582   *          ]
  2583   *      },
  2584   *      "login_chat_queues":{
  2585   *          "chat_queue":[
  2586   *              {"@chat_queue_description":"","@chat_queue_id":"","@chat_queue_name":""},
  2587   *              {"@chat_queue_description":"","@chat_queue_id":"","@chat_queue_name":""}
  2588   *          ]
  2589   *      },
  2590   *      "outdial_groups":{
  2591   *          "group":[
  2592   *              {"@billing_key":"","@dial_group_desc":"","@dial_group_id":"44","@dial_group_name":"Geoff Dial Test","@dial_mode":"PREDICTIVE"},
  2593   *              {"@billing_key":"2","@dial_group_desc":"AutoDial Configured Dial Group","@dial_group_id":"46","@dial_group_name":"Phone Only test5","@dial_mode":"PREDICTIVE"},
  2594   *              {"@billing_key":"","@dial_group_desc":"Test","@dial_group_id":"200000","@dial_group_name":"Test","@dial_mode":"PREDICTIVE"},
  2595   *              {"@billing_key":"","@dial_group_desc":"Test","@dial_group_id":"200010","@dial_group_name":"Carissa's Test Group","@dial_mode":"PREDICTIVE"}
  2596   *          ]
  2597   *      },"skill_profiles":{
  2598   *          "profile":[
  2599   *              {"@profile_desc":"","@profile_id":"571","@profile_name":"skill1"},
  2600   *              {"@profile_desc":"","@profile_id":"572","@profile_name":"skill2"}
  2601   *          ]
  2602   *      },
  2603   *      "requeue_gates":{
  2604   *          "gate_group":[
  2605   *              {
  2606   *                  "@gate_group_id":"18",
  2607   *                  "@group_name":"new gate group",
  2608   *                  "gates":{
  2609   *                      "gate":[
  2610   *                          {"@gate_desc":"","@gate_id":"37","@gate_name":"test"},
  2611   *                          {"@gate_desc":"","@gate_id":"43","@gate_name":"test gate three"},
  2612   *                          {"@gate_desc":"","@gate_id":"42","@gate_name":"test gate two"}
  2613   *                      ]
  2614   *                  },
  2615   *                  "skills":{
  2616   *                      "skill":[
  2617   *                          {"@skill_desc":"","@skill_id":"58","@skill_name":"one"},
  2618   *                          {"@skill_desc":"","@skill_id":"59","@skill_name":"two"},
  2619   *                      ]
  2620   *                  }
  2621   *              }
  2622   *          ]
  2623   *      },
  2624   *      "chat_rooms":{},
  2625   *      "scripts": {
  2626   *           "script": {
  2627   *               "@script_id": "15",
  2628   *               "@script_name": "Don't Read This Script"
  2629   *           }
  2630   *      },
  2631   *      "campaigns": {
  2632   *          "campaign": {
  2633   *              "@allow_lead_updates": "",
  2634   *              "@campaign_id": "",
  2635   *              "@campaign_name": "",
  2636   *              "@survey_id": "",
  2637   *              "@survey_name": "",
  2638   *              "custom_labels": {
  2639   *                  "@aux_1_label": "",
  2640   *                  "@aux_2_label": "",
  2641   *                  "@aux_3_label": "",
  2642   *                  "@aux_4_label": "",
  2643   *                  "@aux_5_label": ""
  2644   *              },
  2645   *              "generic_key_value_pairs": {}
  2646   *          }
  2647   *      },
  2648   *      "account_countries":{
  2649   *          "country":[
  2650   *              {"@country_id":"BRA"},{"@country_id":"FRA"},{"@country_id":"GER"}
  2651   *          ]
  2652   *      }
  2653   *   }
  2654   * }
  2655   */
  2656  LoginRequest.prototype.processResponse = function(response) {
  2657      var resp = response.ui_response;
  2658      var status = resp.status['#text'];
  2659      var model = UIModel.getInstance();
  2660      var formattedResponse = utils.buildDefaultResponse(response);
  2661      if(status === 'OK'){
  2662          if(!model.isLoggedInIS){
  2663              // save login packet properties to UIModel
  2664              model.loginPacket = response;
  2665              model.applicationSettings.isLoggedInIS = true;
  2666              model.applicationSettings.isTcpaSafeMode = utils.getText(resp, 'tcpa_safe_mode') === "1";
  2667              model.applicationSettings.pciEnabled = utils.getText(resp, 'pci_enabled') === "1";
  2668              model.chatSettings.alias = utils.getText(resp, 'first_name') + " " + utils.getText(resp, 'last_name');
  2669              model.agentSettings.loginDTS = new Date();
  2670              model.agentSettings.maxBreakTime = utils.getText(resp, 'max_break_time');
  2671              model.agentSettings.maxLunchTime = utils.getText(resp, 'max_lunch_time');
  2672              model.agentSettings.firstName = utils.getText(resp, 'first_name');
  2673              model.agentSettings.lastName = utils.getText(resp, 'last_name');
  2674              model.agentSettings.email = utils.getText(resp, 'email');
  2675              model.agentSettings.agentId = utils.getText(resp, 'agent_id');
  2676              model.agentSettings.externalAgentId = utils.getText(resp, 'external_agent_id');
  2677              model.agentSettings.agentType = utils.getText(resp, 'agent_type');
  2678              model.agentSettings.realAgentType = utils.getText(resp, 'real_agent_type');
  2679              model.agentSettings.defaultLoginDest = utils.getText(resp, 'default_login_dest');
  2680              model.agentSettings.altDefaultLoginDest = utils.getText(resp, 'alt_default_login_dest');
  2681              model.agentSettings.initLoginState = utils.getText(resp, 'init_login_state');
  2682              model.agentSettings.initLoginStateLabel = utils.getText(resp, 'init_login_state_label');
  2683              model.agentSettings.outboundManualDefaultRingtime = utils.getText(resp, 'outbound_manual_default_ringtime');
  2684              model.agentSettings.isOutboundPrepay = utils.getText(resp, 'outbound_prepay') === "1";
  2685              model.agentSettings.phoneLoginPin = utils.getText(resp, 'phone_login_pin');
  2686              model.agentSettings.username = model.loginRequest.username;
  2687              model.agentPermissions.allowCallControl = utils.getText(resp, 'allow_call_control') === "1";
  2688              model.agentPermissions.allowChat = utils.getText(resp, 'allow_chat') === "1";
  2689              model.agentPermissions.showLeadHistory = utils.getText(resp, 'show_lead_history') === "1";
  2690              model.agentPermissions.allowManualOutboundGates = utils.getText(resp, 'allow_manual_outbound_gates') === "1";
  2691              model.agentPermissions.allowOffHook = utils.getText(resp, 'allow_off_hook') === "1";
  2692              model.agentPermissions.allowManualCalls = utils.getText(resp, 'allow_manual_calls') === "1";
  2693              model.agentPermissions.allowManualPass = utils.getText(resp, 'allow_manual_pass') === "1";
  2694              model.agentPermissions.allowManualIntlCalls = utils.getText(resp, 'allow_manual_intl_calls') === "1";
  2695              model.agentPermissions.allowLoginUpdates = utils.getText(resp, 'allow_login_updates') === "1";
  2696              model.agentPermissions.allowInbound = utils.getText(resp, 'allow_inbound') === "1";
  2697              model.agentPermissions.allowOutbound = utils.getText(resp, 'allow_outbound') === "1";
  2698              model.agentPermissions.allowBlended = utils.getText(resp, 'allow_blended') === "1";
  2699              model.agentPermissions.allowLoginControl = utils.getText(resp, 'allow_login_control') === "1";
  2700              model.agentPermissions.allowCrossQueueRequeue = utils.getText(resp, 'allow_cross_gate_requeue') === "1";
  2701              model.agentPermissions.disableSupervisorMonitoring = utils.getText(resp, 'disable_supervisor_monitoring') === "1";
  2702              model.agentPermissions.allowAutoAnswer = utils.getText(resp, 'allow_auto_answer') === "1";
  2703              model.agentPermissions.defaultAutoAnswerOn = utils.getText(resp, 'default_auto_answer_on') === "1";
  2704              model.agentPermissions.allowHistoricalDialing = utils.getText(resp, 'allow_historical_dialing') === "1";
  2705              model.agentPermissions.allowAgentStats = utils.getText(resp, 'allow_agent_stats') === "1";
  2706              model.agentPermissions.allowCampaignStats = utils.getText(resp, 'allow_camp_stats') === "1";
  2707              model.agentPermissions.allowGateStats = utils.getText(resp, 'allow_gate_stats') === "1";
  2708              model.agentPermissions.allowChatStats = utils.getText(resp, 'allow_chat_stats') === "1";
  2709              model.outboundSettings.defaultDialGroup = utils.getText(resp, 'phone_login_dial_group');
  2710              if(response.ui_response.allow_lead_inserts && typeof resp.insert_campaigns !== 'undefined' && response.ui_response.insert_campaigns.campaign){
  2711                  model.agentPermissions.allowLeadInserts = utils.getText(resp, 'allow_lead_inserts') === "1";
  2712              }
  2713              // Set collection values
  2714              model.outboundSettings.availableCampaigns = _processCampaigns(response);
  2715              model.chatSettings.availableChatQueues = utils.processResponseCollection(response.ui_response, "login_chat_queues", "chat_queue");
  2716              processChatQueueDnis(model.chatSettings, response);
  2717              model.chatSettings.availableChatRequeueQueues = utils.processResponseCollection(response.ui_response, "chat_requeue_queues", "chat_group");
  2718              model.inboundSettings.availableQueues = utils.processResponseCollection(response.ui_response, "login_gates", "gate");
  2719              model.inboundSettings.availableSkillProfiles = utils.processResponseCollection(response.ui_response, "skill_profiles", "profile");
  2720              model.inboundSettings.availableRequeueQueues = utils.processResponseCollection(response.ui_response, "requeue_gates", "gate_group");
  2721              model.chatSettings.availableChatRooms = utils.processResponseCollection(response.ui_response, "chat_rooms", "room");
  2722              model.scriptSettings.availableScripts = utils.processResponseCollection(response.ui_response, "scripts", "script");
  2723              model.agentSettings.callerIds = utils.processResponseCollection(response.ui_response, "caller_ids", "caller_id");
  2724              model.agentSettings.availableAgentStates = utils.processResponseCollection(response.ui_response, "agent_states", "agent_state");
  2725              model.applicationSettings.availableCountries = utils.processResponseCollection(response.ui_response, "account_countries", "country");
  2726              model.outboundSettings.insertCampaigns = utils.processResponseCollection(response.ui_response, "insert_campaigns", "campaign");
  2727              var dialGroups = utils.processResponseCollection(response.ui_response, "outdial_groups", "group");
  2728              // set boolean values
  2729              for(var dg = 0; dg < dialGroups.length; dg++){
  2730                  var group = dialGroups[dg];
  2731                  group.allowLeadSearch = group.allowLeadSearch === "YES";
  2732                  group.allowPreviewLeadFilters = group.allowPreviewLeadFilters === "1";
  2733                  group.progressiveEnabled = group.progressiveEnabled === "1";
  2734                  group.requireFetchedLeadsCalled = group.requireFetchedLeadsCalled === "1";
  2735                  group.hciType = parseInt(group.hciEnabled) || 0;
  2736                  group.hciEnabled = group.hciEnabled === "1" || group.hciEnabled === "2";
  2737                  group.hciClicker = group.hciClicker === "1";
  2738              }
  2739              model.outboundSettings.availableOutdialGroups = dialGroups;
  2740          }
  2741          formattedResponse.agentSettings = model.agentSettings;
  2742          formattedResponse.agentPermissions = model.agentPermissions;
  2743          formattedResponse.applicationSettings = model.applicationSettings;
  2744          formattedResponse.chatSettings = model.chatSettings;
  2745          formattedResponse.connectionSettings = model.connectionSettings;
  2746          formattedResponse.inboundSettings = model.inboundSettings;
  2747          formattedResponse.outboundSettings = model.outboundSettings;
  2748          formattedResponse.scriptSettings = model.scriptSettings;
  2749      }else if(status === 'RESTRICTED'){
  2750          formattedResponse.message = "Invalid IP Address";
  2751          utils.logMessage(LOG_LEVELS.WARN, formattedResponse.message, response);
  2752      }else{
  2753          formattedResponse.message = "Invalid Username or password";
  2754          utils.logMessage(LOG_LEVELS.WARN, formattedResponse.message, response);
  2755      }
  2756      return formattedResponse;
  2757  };
  2758  function _processCampaigns(response){
  2759      var campaigns = [];
  2760      var campaignsRaw = null;
  2761      if(typeof response.ui_response.campaigns.campaign !== 'undefined'){
  2762          campaignsRaw = response.ui_response.campaigns.campaign;
  2763      }
  2764      if(campaignsRaw){
  2765          if(!Array.isArray(campaignsRaw)) {
  2766              campaignsRaw = [campaignsRaw];
  2767          }
  2768          for(var c = 0; c < campaignsRaw.length; c++){
  2769              campaigns.push(_processCampaign(campaignsRaw[c]));
  2770          }
  2771      }
  2772      return campaigns;
  2773  }
  2774  function _processCampaign(campaignRaw) {
  2775      // single campaign object
  2776      var campaignId = campaignRaw['@campaign_id'];
  2777      var allowLeadUpdates = campaignRaw['@allow_lead_updates']; // 0 = no update, 1 = allow phone update, 2 = don't allow phone update
  2778      UIModel.getInstance().agentPermissions.allowLeadUpdatesByCampaign[campaignId] = allowLeadUpdates;
  2779      var customLabels = campaignRaw['custom_labels'];
  2780      var labelArray = [];
  2781      for (var p in customLabels) {
  2782          var label = p.replace(/@/, ''); // remove leading '@'
  2783          var obj = {};
  2784          obj[label] = customLabels[p];
  2785          labelArray.push(obj);
  2786      }
  2787      return {
  2788          campaignId: campaignId,
  2789          campaignName: campaignRaw['@campaign_name'],
  2790          surveyId: campaignRaw['@survey_id'],
  2791          surveyName: campaignRaw['@survey_name'],
  2792          customLabels: labelArray,
  2793          allowLeadUpdates: allowLeadUpdates
  2794      };
  2795  }
  2796  /**
  2797   * example packet
  2798   *  {
  2799   *      "chat_queue":[
  2800   *          {
  2801   *              "@chat_queue_desc":"",
  2802   *              "@chat_queue_id":"74",
  2803   *              "@chat_queue_name":"Please don't delete"
  2804   *          },
  2805   *          {
  2806   *              "@chat_queue_desc":"blah",
  2807   *              "@chat_queue_id":"131",
  2808   *              "@chat_queue_name":"cris chat queue",
  2809   *              "dnis":[
  2810   *                  {"#text":"5555551215"},
  2811   *                  {"#text":"5555554444"},
  2812   *                  {"#text":"8885551212"},
  2813   *                  {"#text":"97687"}
  2814   *              ]
  2815   *          }
  2816   *      ]
  2817   *   }
  2818   *
  2819   *
  2820   *      This function will format the dnis list and put them back on chatSettings.availableChatQueues
  2821   **/
  2822  function processChatQueueDnis(chatSettings, response) {
  2823      var queues = chatSettings.availableChatQueues;
  2824      var rawQueues = response.ui_response.login_chat_queues.chat_queue;
  2825      if(!Array.isArray(rawQueues)) {
  2826          rawQueues = [rawQueues];
  2827      }
  2828      for(var i = 0; i < queues.length; i++) {
  2829          var queue = queues[i];
  2830          var rawQueue = {};
  2831          for (var j = 0; j < rawQueues.length; j++) {
  2832              var rq = rawQueues[j];
  2833              if(rq['@chat_queue_id'] === queue.chatQueueId) {
  2834                  rawQueue = rq;
  2835                  break;
  2836              }
  2837          }
  2838          if(rawQueue.dnis) {
  2839              if(!Array.isArray(rawQueue.dnis)) {
  2840                  rawQueue.dnis = [rawQueue.dnis];
  2841              }
  2842              // update the dnis array to just be a list
  2843              queue.dnis = rawQueue.dnis.map(function(d) {
  2844                  return d['#text'];
  2845              });
  2846          }
  2847      }
  2848  }
  2849  var LogoutRequest = function(agentId, message, isSupervisor) {
  2850      this.agentId = agentId;
  2851      this.message = message || "";
  2852      this.isSupervisor = isSupervisor;
  2853  };
  2854  LogoutRequest.prototype.formatJSON = function() {
  2855      var msg = {
  2856          "ui_request": {
  2857              "@destination":"IQ",
  2858              "@type":MESSAGE_TYPES.LOGOUT,
  2859              "@message_id":utils.getMessageId(),
  2860              "response_to":"",
  2861              "agent_id":{
  2862                  "#text":this.agentId
  2863              },
  2864              "message":{
  2865                  "#text":this.message
  2866              }
  2867          }
  2868      };
  2869      return JSON.stringify(msg);
  2870  };
  2871  var OffhookInitRequest = function() {
  2872  };
  2873  OffhookInitRequest.prototype.formatJSON = function() {
  2874      var msg = {
  2875          "ui_request": {
  2876              "@destination":"IQ",
  2877              "@type":MESSAGE_TYPES.OFFHOOK_INIT,
  2878              "@message_id":utils.getMessageId(),
  2879              "response_to":"",
  2880              "agent_id":{
  2881                  "#text":UIModel.getInstance().agentSettings.agentId
  2882              },
  2883              "dial_dest":{
  2884                  "#text":UIModel.getInstance().agentSettings.dialDest
  2885              }
  2886          }
  2887      };
  2888      return JSON.stringify(msg);
  2889  };
  2890  /*
  2891   * This class is responsible for handling an off-hook-init response packet from IntelliQueue.
  2892   * If the offhookinit is successful, it will go into the UIModel and set the isOffhook variable
  2893   * to true.
  2894   *
  2895   * {"ui_response":{
  2896   *      "@message_id":"UI2005",
  2897   *      "@response_to":"",
  2898   *      "@type":"OFF-HOOK-INIT",
  2899   *      "status":{"#text":"OK|FAILURE"},
  2900   *      "monitoring":{"#text:"TRUE|FALSE"},
  2901   *      "message":{},
  2902   *      "detail":{}
  2903   *    }
  2904   * }
  2905   */
  2906  OffhookInitRequest.prototype.processResponse = function(response) {
  2907      var status = response.ui_response.status['#text'];
  2908      var formattedResponse = utils.buildDefaultResponse(response);
  2909      if(status === 'OK') {
  2910          var isMonitoring = utils.getText(response.ui_response, "monitoring");
  2911          UIModel.getInstance().offhookInitPacket = response;
  2912          UIModel.getInstance().agentSettings.isOffhook = true;
  2913          UIModel.getInstance().agentSettings.isMonitoring = isMonitoring;
  2914          formattedResponse.monitoring = isMonitoring;
  2915      } else {
  2916          if(formattedResponse.message === "") {
  2917              formattedResponse.message = "Unable to process offhook request";
  2918          }
  2919          utils.logMessage(LOG_LEVELS.WARN, formattedResponse.message + ' ' + formattedResponse.detail, response);
  2920      }
  2921      return formattedResponse;
  2922  };
  2923  var OffhookTermRequest = function() {
  2924  };
  2925  OffhookTermRequest.prototype.formatJSON = function() {
  2926      var msg = {
  2927          "ui_request": {
  2928              "@destination":"IQ",
  2929              "@type":MESSAGE_TYPES.OFFHOOK_TERM,
  2930              "@message_id":utils.getMessageId(),
  2931              "response_to":"",
  2932              "agent_id":{
  2933                  "#text":UIModel.getInstance().agentSettings.agentId
  2934              }
  2935          }
  2936      };
  2937      return JSON.stringify(msg);
  2938  };
  2939  /*
  2940   * Process an OFF-HOOK-TERM packet and update various variables in the UI
  2941   *
  2942   * {"ui_notification":{
  2943   *      "@message_id":"IQ10012016080217135001344",
  2944   *      "@response_to":"",
  2945   *      "@type":"OFF-HOOK-TERM",
  2946   *      "agent_id":{"#text":"1"},
  2947   *      "start_dts":{"#text":"2016-08-02 17:11:38"},
  2948   *      "end_dts":{"#text":"2016-08-02 17:14:07"},
  2949   *      "monitoring":{"#text":"0"}
  2950   *    }
  2951   * }
  2952   */
  2953  OffhookTermRequest.prototype.processResponse = function(data) {
  2954      var notif = data.ui_notification;
  2955      var monitoring = utils.getText(notif, "monitoring") === '1';
  2956      var model = UIModel.getInstance();
  2957      model.agentSettings.wasMonitoring = monitoring;
  2958      model.offhookTermPacket = data;
  2959      model.agentSettings.isOffhook = false;
  2960      model.agentSettings.isMonitoring = false;
  2961      var formattedResponse = {
  2962          status: "OK",
  2963          agentId: utils.getText(notif, "agent_id"),
  2964          startDts: utils.getText(notif, "start_dts"),
  2965          endDts: utils.getText(notif, "end_dts"),
  2966          monitoring: monitoring
  2967      };
  2968      return formattedResponse;
  2969  };
  2970  var OneToOneOutdialRequest = function(destination, callerId, ringTime, countryId, gateId) {
  2971      this.destination = destination;
  2972      this.callerId = callerId;
  2973      this.ringTime = ringTime || "60";
  2974      this.countryId = countryId || "USA";
  2975      this.gateId = gateId || "";
  2976  };
  2977  OneToOneOutdialRequest.prototype.formatJSON = function() {
  2978      var msg = {
  2979          "ui_request": {
  2980              "@destination":"IQ",
  2981              "@type":MESSAGE_TYPES.ONE_TO_ONE_OUTDIAL,
  2982              "@message_id":utils.getMessageId(),
  2983              "response_to":"",
  2984              "agent_id":{
  2985                  "#text":utils.toString(UIModel.getInstance().agentSettings.agentId)
  2986              },
  2987              "destination":{
  2988                  "#text":utils.toString(this.destination)
  2989              },
  2990              "ring_time":{
  2991                  "#text":utils.toString(this.ringTime)
  2992              },
  2993              "caller_id":{
  2994                  "#text":utils.toString(this.callerId)
  2995              },
  2996              "country_id":{
  2997                  "#text":utils.toString(this.countryId)
  2998              },
  2999              "gate_id":{
  3000                  "#text":utils.toString(this.gateId)
  3001              }
  3002          }
  3003      };
  3004      return JSON.stringify(msg);
  3005  };
  3006  var OneToOneOutdialCancelRequest = function(uii) {
  3007      this.uii = uii
  3008  };
  3009  /*
  3010   * This class is responsible for creating a new packet to cancel
  3011   * an in-progress outbound call.
  3012   */
  3013  OneToOneOutdialCancelRequest.prototype.formatJSON = function() {
  3014      var msg = {
  3015          "ui_request": {
  3016              "@destination":"IQ",
  3017              "@type":MESSAGE_TYPES.ONE_TO_ONE_OUTDIAL_CANCEL,
  3018              "@message_id":utils.getMessageId(),
  3019              "response_to":"",
  3020              "agent_id":{
  3021                  "#text":utils.toString(UIModel.getInstance().agentSettings.agentId)
  3022              },
  3023              "uii":{
  3024                  "#text":utils.toString(this.uii)
  3025              }
  3026          }
  3027      };
  3028      return JSON.stringify(msg);
  3029  };
  3030  var PauseRecordRequest = function(record) {
  3031      this.record = record;
  3032  };
  3033  /*
  3034   * {"ui_request":{
  3035   *      "@destination":"IQ",
  3036   *      "@message_id":"UI200809291036128",
  3037   *      "@response_to":"",
  3038   *      "@type":"PAUSE-RECORD",
  3039   *      "agent_id":{"#text":"1856"},
  3040   *      "uii":{"#text":"200808291035510000000900029412"},
  3041   *      "record":{"#text":"TRUE | FALSE"},
  3042   *      "pause":{"#text":"10"}
  3043   *    }
  3044   * }
  3045   */
  3046  PauseRecordRequest.prototype.formatJSON = function() {
  3047      var model = UIModel.getInstance();
  3048      var pauseTime = "10";
  3049      if(model.currentCall.agentRecording && model.currentCall.agentRecording.pause){
  3050          pauseTime = model.currentCall.agentRecording.pause;
  3051      }
  3052      var msg = {
  3053          "ui_request": {
  3054              "@destination":"IQ",
  3055              "@type":MESSAGE_TYPES.PAUSE_RECORD,
  3056              "@message_id":utils.getMessageId(),
  3057              "@response_to":"",
  3058              "agent_id":{
  3059                  "#text":utils.toString(model.currentCall.agentId)
  3060              },
  3061              "uii":{
  3062                  "#text":utils.toString(model.currentCall.uii)
  3063              },
  3064              "record":{
  3065                  "#text":utils.toString(this.record === true ? "TRUE" : "FALSE")
  3066              },
  3067              "pause":{
  3068                  "#text":utils.toString(pauseTime)
  3069              }
  3070          }
  3071      };
  3072      return JSON.stringify(msg);
  3073  };
  3074  /*
  3075   * This class processes PAUSE-RECORD packets rec'd from IQ.
  3076   *
  3077   * {"ui_response":{
  3078   *      "@message_id":"IQ982008082910361503344",
  3079   *      "@response_to":"",
  3080   *      "@type":"PAUSE-RECORD",
  3081   *      "uii":{"#text":"200808291035510000000900029412"},
  3082   *      "status":{"#text":"OK | FAILURE"},
  3083   *      "message":{},
  3084   *      "detail":{},
  3085   *      "state":{"#text":"RECORDING | PAUSED"},
  3086   *      "pause":{"#text":"10"}
  3087   *    }
  3088   * }
  3089   */
  3090  PauseRecordRequest.prototype.processResponse = function(response) {
  3091      var resp = response.ui_response;
  3092      var formattedResponse = utils.buildDefaultResponse(response);
  3093      var currUII = "";
  3094      if(UIModel.getInstance().currentCall.uii){
  3095          currUII = UIModel.getInstance().currentCall.uii;
  3096      }
  3097      formattedResponse.uii = utils.getText(resp, 'uii');
  3098      formattedResponse.state = utils.getText(resp, 'state');
  3099      formattedResponse.pause = utils.getText(resp, 'pause');
  3100      if(formattedResponse.status === "OK"){
  3101          // make sure we are talking about the same call
  3102          if(formattedResponse.uii === currUII) {
  3103              if(formattedResponse.message === ""){
  3104                  formattedResponse.message = "Broadcasting new record state of " + formattedResponse.state;
  3105              }
  3106              utils.logMessage(LOG_LEVELS.DEBUG, "Broadcasting new record state of " + formattedResponse.state, response);
  3107          }else{
  3108              utils.logMessage(LOG_LEVELS.DEBUG, "Pause Record Response is for a different call...discarding", response);
  3109          }
  3110      }else{
  3111          if(formattedResponse.message === ""){
  3112              formattedResponse.message = "Error processing PAUSE-RECORD request." + formattedResponse.message + "\n" + formattedResponse.detail;
  3113          }
  3114          utils.logMessage(LOG_LEVELS.WARN, formattedResponse.message, response);
  3115      }
  3116      return formattedResponse;
  3117  };
  3118  var PingCallRequest = function() {
  3119      
  3120  };
  3121  PingCallRequest.prototype.formatJSON = function() {
  3122      var msg = {
  3123          "ui_request": {
  3124              "@destination":"IQ",
  3125              "@type":MESSAGE_TYPES.PING_CALL,
  3126              "@message_id":utils.getMessageId(),
  3127              "@response_to":"",
  3128              "agent_id":{
  3129                  "#text":UIModel.getInstance().currentCall.agentId
  3130              },
  3131              "uii":{
  3132                  "#text":UIModel.getInstance().currentCall.uii
  3133              }
  3134          }
  3135      };
  3136      return JSON.stringify(msg);
  3137  };
  3138  var PreviewDialRequest = function(action, searchFields, requestId, leadPhone) {
  3139      this.agentId = UIModel.getInstance().agentSettings.agentId;
  3140      this.searchFields = searchFields || [];
  3141      this.requestId = requestId || "";
  3142      this.action = action || "";
  3143      this.leadPhone = leadPhone || "";   // pipe leads only
  3144  };
  3145  /*
  3146   * searchFields = [
  3147   *  {key: "name", value: "Danielle"},
  3148   *  {key: "number", value: "5555555555"
  3149   * ];
  3150   */
  3151  PreviewDialRequest.prototype.formatJSON = function() {
  3152      var fields = {};
  3153      for(var i =0; i < this.searchFields.length; i++){
  3154          var fieldObj = this.searchFields[i];
  3155          fields[fieldObj.key] = { "#text" : utils.toString(fieldObj.value) };
  3156      }
  3157      var msg = {
  3158          "ui_request": {
  3159              "@destination":"IQ",
  3160              "@type":MESSAGE_TYPES.PREVIEW_DIAL,
  3161              "@message_id":utils.getMessageId(),
  3162              "@action":this.action,
  3163              "@response_to":"",
  3164              "agent_id":{
  3165                  "#text":utils.toString(UIModel.getInstance().agentSettings.agentId)
  3166              },
  3167              "pending_request_id":{
  3168                  "#text":utils.toString(this.requestId)
  3169              },
  3170              "lead_phone":{
  3171                  "#text":utils.toString(this.leadPhone)
  3172              },
  3173              "search_fields": fields
  3174                  // { "name": {"#text": "Danielle" } }
  3175          }
  3176      };
  3177      return JSON.stringify(msg);
  3178  };
  3179  /*
  3180   * This class is responsible for handling PREVIEW-DIAL packets received
  3181   * from the dialer. It will save a copy of it in the UIModel.
  3182   *
  3183   * {"dialer_request":{
  3184   *      "@action":"", // <-- empty for Preview fetch, otherwise "SEARCH"
  3185   *      "@callbacks":"TRUE|FALSE"
  3186   *      ,"@message_id":"ID2008091513163400220",
  3187   *      "@response_to":"",
  3188   *      "@type":"PREVIEW_DIAL",
  3189   *      "dial_group_id":{"#text":"200018"},
  3190   *      "account_id":{"#text":"99999999"},
  3191   *      "agent_id":{"#text":"1810"},
  3192   *      "is_insert":{"#text":"TRUE|FALSE"}, <--- TRUE if search triggered by insert
  3193   *      "destinations":{
  3194   *          "lead":[
  3195   *              {
  3196   *                  "@aux_data1":"","@aux_data2":"","@aux_data3":"","@aux_data4":"","@aux_data5":"",
  3197   *                  "@aux_phone":"","@campaign_id":"51","@destination":"9548298548","@dnis":"1112223333",
  3198   *                  "@extern_id":"amanda","@lead_id":"2646","@lead_state":"PENDING","@live_answer_msg":"",
  3199   *                  "@mach_answer_msg":"","@machine_detect":"FALSE","@request_key":"IQ982008091516241101125",
  3200   *                  "@valid_until":"2008-09-15 17:24:11","extern_id":{"#text":"9548298548"},
  3201   *                  "first_name":{"#text":"Amanda"},"mid_name":{"#text":"Amanda"},"last_name":{"#text":"Machutta2"},
  3202   *                  "address1":{},"address2":{},"city":{},"state":{},"zip":{},"aux_greeting":{},
  3203   *                  "aux_external_url":{}, "app_url":{}
  3204   *              },
  3205   *          ]
  3206   *      }
  3207   *    }
  3208   * }
  3209   */
  3210  PreviewDialRequest.prototype.processResponse = function(notification) {
  3211      var notif = notification.dialer_request;
  3212      var model = UIModel.getInstance();
  3213      var leads = utils.processResponseCollection(notif, 'destinations', 'lead');
  3214      // send over requestId (as well as requestKey for backwards compatibility)
  3215      // to match previewLeadState.notification property
  3216      for(var l = 0; l < leads.length; l++) {
  3217          var lead = leads[l];
  3218          lead.requestId = lead.requestKey;
  3219          lead.ani = lead.destination; // add ani prop since used in new call packet & update lead
  3220          // In case of a single lead returned, the XML converter to JSON will add lead as an object and not an array
  3221          //
  3222          if (!Array.isArray(notif.destinations.lead)) {
  3223              notif.destinations.lead = [notif.destinations.lead];
  3224          }
  3225          // parse extra data correctly
  3226          try {
  3227              var notifLead = notif.destinations.lead[l];
  3228              if(notifLead.extra_data) {
  3229                  // if this lead doesn't match the current lead, find it from the notification
  3230                  if(notifLead['@lead_id'] !== lead.leadId) {
  3231                      notifLead = (notif.destinations.lead).filter(
  3232                          function(destLead) {
  3233                              return destLead['@lead_id'] === lead.leadId;
  3234                          }
  3235                      );
  3236                  }
  3237                  delete lead.extraDatas;
  3238                  lead.extraData = {};
  3239                  for(var key in notifLead.extra_data) {
  3240                      lead.extraData[key] = notifLead.extra_data[key]['#text'];
  3241                  }
  3242              }
  3243          } catch(e) {
  3244              console.warn('error parsing lead extra data: ' + e);
  3245          }
  3246      }
  3247      var formattedResponse = {
  3248          action: notif['@action'],
  3249          callbacks: notif['@callbacks'] === "TRUE",
  3250          dialGroupId: utils.getText(notif,"dial_group_id"),
  3251          accountId: utils.getText(notif,"account_id"),
  3252          agentId: utils.getText(notif,"agent_id"),
  3253          isInsert: utils.getText(notif,"is_insert"),
  3254          leads: leads
  3255      };
  3256      if(notif['@callbacks'] === 'TRUE'){
  3257          utils.logMessage(LOG_LEVELS.INFO, "New CALLBACK packet request rec'd from dialer", notification);
  3258          // clear callbacks??
  3259          //model.callbacks = [];
  3260          for(var l = 0; l < leads.length; l++){
  3261              var lead = leads[l];
  3262              model.callbacks.push(lead);
  3263          }
  3264      }else{
  3265          model.outboundSettings.previewDialLeads = leads;
  3266      }
  3267      return formattedResponse;
  3268  };
  3269  var RecordRequest = function(record) {
  3270      this.record = record;
  3271  };
  3272  /*
  3273   * {"ui_request":{
  3274   *      "@destination":"IQ",
  3275   *      "@message_id":"UI200809291036128",
  3276   *      "@response_to":"",
  3277   *      "@type":"RECORD",
  3278   *      "agent_id":{"#text":"1856"},
  3279   *      "uii":{"#text":"200808291035510000000900029412"},
  3280   *      "record":{"#text":"TRUE | FALSE"}
  3281   *    }
  3282   * }
  3283   */
  3284  RecordRequest.prototype.formatJSON = function() {
  3285      var model = UIModel.getInstance();
  3286      var msg = {
  3287          "ui_request": {
  3288              "@destination":"IQ",
  3289              "@type":MESSAGE_TYPES.RECORD,
  3290              "@message_id":utils.getMessageId(),
  3291              "@response_to":"",
  3292              "agent_id":{
  3293                  "#text":utils.toString(model.currentCall.agentId)
  3294              },
  3295              "uii":{
  3296                  "#text":utils.toString(model.currentCall.uii)
  3297              },
  3298              "record":{
  3299                  "#text": this.record === true ? "TRUE" : "FALSE"
  3300              }
  3301          }
  3302      };
  3303      return JSON.stringify(msg);
  3304  };
  3305  /*
  3306   * This class processes RECORD packets rec'd from IQ.
  3307   *
  3308   * {"ui_response":{
  3309   *      "@message_id":"IQ982008082910361503344",
  3310   *      "@response_to":"",
  3311   *      "@type":"RECORD",
  3312   *      "uii":{"#text":"200808291035510000000900029412"},
  3313   *      "status":{"#text":"OK"},
  3314   *      "message":{},
  3315   *      "detail":{},
  3316   *      "state":{"#text":"RECORDING | STOPPED"}
  3317   *    }
  3318   * }
  3319   */
  3320  RecordRequest.prototype.processResponse = function(response) {
  3321      var resp = response.ui_response;
  3322      var formattedResponse = utils.buildDefaultResponse(response);
  3323      var currUII = "";
  3324      if(UIModel.getInstance().currentCall.uii){
  3325          currUII = UIModel.getInstance().currentCall.uii;
  3326      }
  3327      formattedResponse.uii = utils.getText(resp, 'uii');
  3328      formattedResponse.state = utils.getText(resp, 'state');
  3329      if(formattedResponse.status === "OK"){
  3330          // make sure we are talking about the same call
  3331          if(formattedResponse.uii === currUII) {
  3332              if(formattedResponse.message === ""){
  3333                  formattedResponse.message = "Broadcasting new record state of " + formattedResponse.state;
  3334              }
  3335              utils.logMessage(LOG_LEVELS.DEBUG, formattedResponse.message, response);
  3336          }else{
  3337              utils.logMessage(LOG_LEVELS.DEBUG, "Record Response is for a different call...discarding", response);
  3338          }
  3339      }else{
  3340          if(formattedResponse.message === ""){
  3341              formattedResponse.message = "Error processing RECORD request." + formattedResponse.message + "\n" + formattedResponse.detail;
  3342          }
  3343          utils.logMessage(LOG_LEVELS.WARN, formattedResponse.message, response);
  3344      }
  3345      return formattedResponse;
  3346  };
  3347  var RequeueRequest = function(queueId, skillId, maintain) {
  3348      this.queueId = queueId;
  3349      this.skillId = skillId;
  3350      this.maintain = maintain;
  3351  };
  3352  RequeueRequest.prototype.formatJSON = function() {
  3353      var msg = {
  3354          "ui_request": {
  3355              "@destination":"IQ",
  3356              "@type":MESSAGE_TYPES.REQUEUE,
  3357              "@message_id":utils.getMessageId(),
  3358              "response_to":"",
  3359              "agent_id":{
  3360                  "#text":UIModel.getInstance().agentSettings.agentId
  3361              },
  3362              "uii":{
  3363                  "#text":UIModel.getInstance().currentCall.uii
  3364              },
  3365              "gate_number":{
  3366                  "#text":utils.toString(this.queueId)
  3367              },
  3368              "skill_id":{
  3369                  "#text":utils.toString(this.skillId)
  3370              },
  3371              "maintain_agent":{
  3372                  "#text":this.maintain === true ? "TRUE" : "FALSE"
  3373              }
  3374          }
  3375      };
  3376      return JSON.stringify(msg);
  3377  };
  3378  /*
  3379   * This class processes RE-QUEUE packets rec'd from IQ.
  3380   *
  3381   * {"ui_response":{
  3382   *      "@message_id":"IQ982008082817165103291",
  3383   *      "@response_to":"UIV220088281716486",
  3384   *      "@type":"RE-QUEUE",
  3385   *      "status":"OK",
  3386   *      "message":"Success.",
  3387   *      "detail":"The re-queue request was successfully processed.",
  3388   *      "agent_id":{"#text":"1856"},
  3389   *      "uii":{"#text":"200808281716090000000900028070"},
  3390   *      "gate_number":{"#text":"19"},
  3391   *      "maintain_agent":{"#text":"FALSE"}
  3392   *    }
  3393   * }
  3394   */
  3395  RequeueRequest.prototype.processResponse = function(response) {
  3396      var resp = response.ui_response;
  3397      var formattedResponse = utils.buildDefaultResponse(response);
  3398      formattedResponse.agentId = utils.getText(resp, 'agent_id');
  3399      formattedResponse.uii = utils.getText(resp, 'uii');
  3400      formattedResponse.queueId = utils.getText(resp, 'gate_number');
  3401      if(formattedResponse.status === "OK"){
  3402      }else{
  3403          var message = "There was an error processing the requeue request. " + formattedResponse.detail;
  3404          utils.logMessage(LOG_LEVELS.WARN, message, response);
  3405      }
  3406      return formattedResponse;
  3407  };
  3408  var ScriptConfigRequest = function(scriptId, version) {
  3409      this.scriptId = scriptId;
  3410      this.version = version || null;
  3411  };
  3412  /*
  3413  * This event is responsible for requesting a script object
  3414  */
  3415  ScriptConfigRequest.prototype.formatJSON = function() {
  3416      var msg = {
  3417          "ui_request": {
  3418              "@destination":"IQ",
  3419              "@message_id":utils.getMessageId(),
  3420              "response_to":"",
  3421              "@type":MESSAGE_TYPES.SCRIPT_CONFIG,
  3422              "agent_id":{
  3423                  "#text":utils.toString(UIModel.getInstance().agentSettings.agentId)
  3424              },
  3425              "script_id": {
  3426                  "#text" : utils.toString(this.scriptId)
  3427              }
  3428          }
  3429      };
  3430      return JSON.stringify(msg);
  3431  };
  3432  /*
  3433   * This class process SCRIPT-CONFIG packets received from IntelliQueue.
  3434   *
  3435   * {"ui_response":{
  3436   *      "@message_id":"IQ982008082817165103294",
  3437   *      "@response_to":"",
  3438   *      "@type":"SCRIPT-CONFIG",
  3439   *      "status":{"#text":"OK"},
  3440   *      "message":{},
  3441   *      "script_id":{"#text":"123"},
  3442   *      "version":{"#text":"1"},
  3443   *      "json":{},
  3444   *   }
  3445   * }
  3446   */
  3447  ScriptConfigRequest.prototype.processResponse = function(response) {
  3448      var resp = response.ui_response;
  3449      var formattedResponse = utils.buildDefaultResponse(response);
  3450      if(formattedResponse.status === "true"){
  3451          formattedResponse.status = true;
  3452          formattedResponse.scriptId = utils.getText(resp, 'script_id');
  3453          formattedResponse.version = utils.getText(resp, 'version');
  3454          formattedResponse.json = utils.getText(resp, 'json');
  3455          // store script on model
  3456          UIModel.getInstance().scriptSettings.loadedScripts[formattedResponse.scriptId] = formattedResponse;
  3457      }else{
  3458          formattedResponse.status = false;
  3459      }
  3460      return formattedResponse;
  3461  };
  3462  var ScriptResultRequest = function(uii, scriptId, jsonResult) {
  3463      this.uii = uii;
  3464      this.scriptId = scriptId;
  3465      this.jsonResult = jsonResult;
  3466  };
  3467  /*
  3468  * This event is responsible for sending the script result object
  3469  */
  3470  ScriptResultRequest.prototype.formatJSON = function() {
  3471      var msg = {
  3472          "ui_request": {
  3473              "@destination":"IQ",
  3474              "@message_id":utils.getMessageId(),
  3475              "response_to":"",
  3476              "@type":MESSAGE_TYPES.SCRIPT_RESULT,
  3477              "agent_id": {
  3478                  "#text" : utils.toString(UIModel.getInstance().agentSettings.agentId)
  3479              },
  3480              "uii":{
  3481                  "#text":utils.toString(this.uii)
  3482              },
  3483              "script_id": {
  3484                  "#text" : utils.toString(this.scriptId)
  3485              },
  3486              "json_result": {
  3487                  "#text": JSON.stringify(this.jsonResult)
  3488              }
  3489          }
  3490      };
  3491      return JSON.stringify(msg);
  3492  };
  3493  var StatsRequest = function() {
  3494      
  3495  };
  3496  /*
  3497   * { "ui_request": {
  3498   *      "@response_to":"",
  3499   *      "@message_id":"IS20160901142437535",
  3500   *      "@type":"STATS"
  3501   *    }
  3502   * }
  3503   */
  3504  StatsRequest.prototype.formatJSON = function() {
  3505      var msg = {
  3506          "ui_request": {
  3507              "@destination":"IS",
  3508              "@type":MESSAGE_TYPES.STATS,
  3509              "@message_id":utils.getMessageId(),
  3510              "@response_to":""
  3511          }
  3512      };
  3513      return JSON.stringify(msg);
  3514  };
  3515  var TcpaSafeRequest = function(action, searchFields, requestId, leadPhone) {
  3516      this.agentId = UIModel.getInstance().agentSettings.agentId;
  3517      this.searchFields = searchFields || [];
  3518      this.requestId = requestId || "";
  3519      this.action = action || "";
  3520      this.leadPhone = leadPhone || "";   // pipe leads only
  3521  };
  3522  /*
  3523   * searchFields = [
  3524   *  {key: "name", value: "Danielle"},
  3525   *  {key: "number", value: "5555555555"
  3526   * ];
  3527   */
  3528  TcpaSafeRequest.prototype.formatJSON = function() {
  3529      var fields = {};
  3530      for(var i =0; i < this.searchFields.length; i++){
  3531          var fieldObj = this.searchFields[i];
  3532          fields[fieldObj.key] = { "#text" : utils.toString(fieldObj.value) };
  3533      }
  3534      var msg = {
  3535          "ui_request": {
  3536              "@destination":"IQ",
  3537              "@type":MESSAGE_TYPES.TCPA_SAFE,
  3538              "@message_id":utils.getMessageId(),
  3539              "@action":this.action,
  3540              "response_to":"",
  3541              "agent_id":{
  3542                  "#text":utils.toString(UIModel.getInstance().agentSettings.agentId)
  3543              },
  3544              "pending_request_id":{
  3545                  "#text":utils.toString(this.requestId)
  3546              },
  3547              "lead_phone":{
  3548                  "#text":utils.toString(this.leadPhone)
  3549              },
  3550              "search_fields": fields
  3551                  // { "name": {"#text": "Danielle"} }
  3552          }
  3553      };
  3554      return JSON.stringify(msg);
  3555  };
  3556  /*
  3557   * This class is responsible for handling TCPA-SAFE packets received
  3558   * from the dialer. It will save a copy of it in the UIModel.
  3559   *
  3560   * {"dialer_request":{
  3561   *      "@action":"",
  3562   *      "@callbacks":"TRUE|FALSE"
  3563   *      ,"@message_id":"ID2008091513163400220",
  3564   *      "@response_to":"",
  3565   *      "@type":"TCPA_SAFE",
  3566   *      "dial_group_id":{"#text":"200018"},
  3567   *      "account_id":{"#text":"99999999"},
  3568   *      "agent_id":{"#text":"1810"},
  3569   *      "is_insert":{"#text":"TRUE|FALSE"}, <--- TRUE if search triggered by insert
  3570   *      "destinations":{
  3571   *          "lead":[
  3572   *              {
  3573   *                  "@aux_data1":"","@aux_data2":"","@aux_data3":"","@aux_data4":"","@aux_data5":"",
  3574   *                  "@aux_phone":"","@campaign_id":"51","@destination":"9548298548","@dnis":"1112223333",
  3575   *                  "@extern_id":"amanda","@lead_id":"2646","@lead_state":"PENDING","@live_answer_msg":"",
  3576   *                  "@mach_answer_msg":"","@machine_detect":"FALSE","@request_key":"IQ982008091516241101125",
  3577   *                  "@valid_until":"2008-09-15 17:24:11","extern_id":{"#text":"9548298548"},
  3578   *                  "first_name":{"#text":"Amanda"},"mid_name":{"#text":"Amanda"},"last_name":{"#text":"Machutta2"},
  3579   *                  "address1":{},"address2":{},"city":{},"state":{},"zip":{},"aux_greeting":{},
  3580   *                  "aux_external_url":{}, "app_url":{}
  3581   *              },
  3582   *          ]
  3583   *      }
  3584   *    }
  3585   * }
  3586   *
  3587   */
  3588  TcpaSafeRequest.prototype.processResponse = function(notification) {
  3589      var notif = notification.dialer_request;
  3590      var model = UIModel.getInstance();
  3591      var leads = utils.processResponseCollection(notif, 'destinations', 'lead');
  3592      // send over requestId (as well as requestKey for backwards compatibility)
  3593      // to match tcpaSafeLeadState.notification property
  3594      for(var l = 0; l < leads.length; l++){
  3595          var lead = leads[l];
  3596          lead.requestId = lead.requestKey;
  3597          lead.ani = lead.destination; // add ani prop since used in new call packet & update lead
  3598          // parse extra data correctly
  3599          try {
  3600              var notifLead = notif.destinations.lead[l];
  3601              if(notifLead.extra_data) {
  3602                  // if this lead doesn't match the current lead, find it from the notification
  3603                  if(notifLead['@lead_id'] !== lead.leadId) {
  3604                      notifLead = (notif.destinations.lead).filter(
  3605                          function(destLead) {
  3606                              return destLead['@lead_id'] === lead.leadId;
  3607                          }
  3608                      );
  3609                  }
  3610                  delete lead.extraDatas;
  3611                  lead.extraData = {};
  3612                  for(var key in notifLead.extra_data) {
  3613                      lead.extraData[key] = notifLead.extra_data[key]['#text'];
  3614                  }
  3615              }
  3616          } catch(e) {
  3617              console.warn('error parsing lead extra data: ' + e);
  3618          }
  3619      }
  3620      var formattedResponse = {
  3621          action: notif['@action'],
  3622          callbacks: notif['@callbacks'] === "TRUE",
  3623          dialGroupId: utils.getText(notif,"dial_group_id"),
  3624          accountId: utils.getText(notif,"account_id"),
  3625          agentId: utils.getText(notif,"agent_id"),
  3626          isInsert: utils.getText(notif,"is_insert"),
  3627          leads: leads
  3628      };
  3629      if(notif['@callbacks'] === 'TRUE'){
  3630          var message = "New CALLBACK packet request rec'd from dialer";
  3631          utils.logMessage(LOG_LEVELS.INFO, message, notification);
  3632          // clear callbacks??
  3633          //model.callbacks = [];
  3634          for(var l = 0; l < leads.length; l++){
  3635              var lead = leads[l];
  3636              model.callbacks.push(lead);
  3637          }
  3638      }else{
  3639          model.outboundSettings.tcpaSafeLeads = leads;
  3640      }
  3641      return formattedResponse;
  3642  };
  3643  var UpdateDialDestinationRequest = function(dialDest, isSoftphoneError) {
  3644      this.dialDest = dialDest;
  3645      this.isSoftphoneError = isSoftphoneError || false;
  3646  };
  3647  /*
  3648   * {"ui_request":{
  3649   *      "@destination":"IQ",
  3650   *      "@type":MESSAGE_TYPES.UPDATE_DIAL_DESTINATION,
  3651   *      "@message_id":"UI200809291036128",
  3652   *      "@response_to":"",
  3653   *      "agent_id":"1",
  3654   *      "dial_dest":{"#text":"blah@something.com"},
  3655   *      "log_softphone_error": {"#text":"TRUE|FALSE"},
  3656   *    }
  3657   * }
  3658   */
  3659  UpdateDialDestinationRequest.prototype.formatJSON = function() {
  3660      var msg = {
  3661          "ui_request": {
  3662              "@destination":"IQ",
  3663              "@type":MESSAGE_TYPES.UPDATE_DIAL_DESTINATION,
  3664              "@message_id":utils.getMessageId(),
  3665              "@response_to":"",
  3666              "agent_id":{
  3667                  "#text":utils.toString(UIModel.getInstance().agentSettings.agentId)
  3668              },
  3669              "dial_dest":{
  3670                  "#text":utils.toString(this.dialDest)
  3671              },
  3672              "log_softphone_error":{
  3673                  "#text":utils.toString(this.isSoftphoneError === true ? "TRUE" : "FALSE")
  3674              }
  3675          }
  3676      };
  3677      return JSON.stringify(msg);
  3678  };
  3679  var XferWarmRequest = function(dialDest, callerId, sipHeaders, countryId) {
  3680      this.dialDest = dialDest;
  3681      this.callerId = callerId || "";
  3682      this.sipHeaders = sipHeaders || [];
  3683      this.countryId = countryId;
  3684  };
  3685  XferWarmRequest.prototype.formatJSON = function() {
  3686      var fields = [];
  3687      for(var i =0; i < this.sipHeaders.length; i++){
  3688          var fieldObj = this.sipHeaders[i];
  3689          fields.push({ '@name' : utils.toString(fieldObj.name), '@value' : utils.toString(fieldObj.value)});
  3690      }
  3691      var msg = {
  3692          "ui_request": {
  3693              "@destination":"IQ",
  3694              "@type":MESSAGE_TYPES.XFER_WARM,
  3695              "@message_id":utils.getMessageId(),
  3696              "@response_to":"",
  3697              "agent_id":{
  3698                  "#text":UIModel.getInstance().agentSettings.agentId
  3699              },
  3700              "uii":{
  3701                  "#text":UIModel.getInstance().currentCall.uii
  3702              },
  3703              "dial_dest":{
  3704                  "#text":utils.toString(this.dialDest)
  3705              },
  3706              "caller_id":{
  3707                  "#text":utils.toString(this.callerId)
  3708              },
  3709              "country_id": {
  3710                  "#text":utils.toString(this.countryId)
  3711              },
  3712              "xfer_header": fields
  3713          }
  3714      };
  3715      return JSON.stringify(msg);
  3716  };
  3717  /*
  3718   * This class processes WARM-XFER packets rec'd from IQ.
  3719   *
  3720   * {"ui_response":{
  3721   *      "@message_id":"IQ10012016082314475000219",
  3722   *      "@response_to":"",
  3723   *      "@type":"WARM-XFER",
  3724   *      "agent_id":{"#text":"1"},
  3725   *      "uii":{"#text":"201608231447590139000000000200"},
  3726   *      "session_id":{"#text":"3"},
  3727   *      "status":{"#text":"OK"},
  3728   *      "dial_dest":{"#text":"3038593775"},
  3729   *      "message":{"#text":"OK"},"detail":{}
  3730   *    }
  3731   * }
  3732   *  Response on CANCEL:
  3733   *  {"ui_response":{
  3734   *      "@message_id":"IQ10012016082315005000264",
  3735   *      "@response_to":"",
  3736   *      "@type":"WARM-XFER",
  3737   *      "agent_id":{"#text":"1"},
  3738   *      "uii":{"#text":"201608231501090139000000000204"},
  3739   *      "session_id":{},
  3740   *      "status":{"#text":"FAILURE"},
  3741   *      "dial_dest":{"#text":"3038593775"},
  3742   *      "message":{"#text":"Transfer CANCELED"},
  3743   *      "detail":{"#text":"NOANSWER after 3 seconds."}
  3744   *    }
  3745   * }
  3746   */
  3747  XferWarmRequest.prototype.processResponse = function(response) {
  3748      var resp = response.ui_response;
  3749      var formattedResponse = utils.buildDefaultResponse(response);
  3750      formattedResponse.agentId = utils.getText(resp, 'agent_id');
  3751      formattedResponse.uii = utils.getText(resp, 'uii');
  3752      formattedResponse.sessionId = utils.getText(resp, 'session_id');
  3753      formattedResponse.dialDest = utils.getText(resp, 'dial_dest');
  3754      if(formattedResponse.status === "OK"){
  3755          utils.logMessage(LOG_LEVELS.DEBUG, "Warm Xfer to " + formattedResponse.dialDest + " processed successfully.", response);
  3756      }else{
  3757          utils.logMessage(LOG_LEVELS.WARN, "There was an error processing the Warm Xfer request. " + formattedResponse.message + "\n" + formattedResponse.detail, response);
  3758      }
  3759      return formattedResponse;
  3760  };
  3761  var XferWarmCancelRequest = function(dialDest) {
  3762      this.dialDest = dialDest;
  3763  };
  3764  XferWarmCancelRequest.prototype.formatJSON = function() {
  3765      var msg = {
  3766          "ui_request": {
  3767              "@destination":"IQ",
  3768              "@type":MESSAGE_TYPES.XFER_WARM_CANCEL,
  3769              "@message_id":utils.getMessageId(),
  3770              "@response_to":"",
  3771              "agent_id":{
  3772                  "#text":UIModel.getInstance().agentSettings.agentId
  3773              },
  3774              "uii":{
  3775                  "#text":UIModel.getInstance().currentCall.uii
  3776              },
  3777              "dial_dest":{
  3778                  "#text":utils.toString(this.dialDest)
  3779              }
  3780          }
  3781      };
  3782      return JSON.stringify(msg);
  3783  };
  3784  var ChatAgentEndRequest = function(agentId, uii){
  3785      this.uii = uii;
  3786      this.agentId = agentId;
  3787  };
  3788  /*
  3789  External Chat :
  3790  when agent submits a chat end request, send "CHAT-AGENT-END" request to IntelliQueue
  3791  {
  3792      "ui_request" : {
  3793          "@destination" : "IQ",
  3794          "@type" : MESSAGE_TYPES.CHAT_AGENT_END,
  3795          "uii":{
  3796              "#text":utils.toString(this.uii)
  3797          },
  3798          "agent_id":{
  3799              "#text":utils.toString(this.agentId)
  3800          }
  3801      }
  3802  }
  3803  */
  3804  ChatAgentEndRequest.prototype.formatJSON = function(){
  3805      var msg = {
  3806          "ui_request" : {
  3807              "@destination" : "IQ",
  3808              "@type" : MESSAGE_TYPES.CHAT_AGENT_END,
  3809              "uii":{
  3810                  "#text":utils.toString(this.uii)
  3811              },
  3812              "agent_id":{
  3813                  "#text":utils.toString(this.agentId)
  3814              }
  3815          }
  3816      };
  3817      return JSON.stringify(msg);
  3818  };
  3819  var ChatAliasRequest = function(alias) {
  3820      this.alias = alias;
  3821  };
  3822  /*
  3823   * This class is responsible for creating the request to change chat alias
  3824   * packet and sending it to intelliservices.
  3825   * {"ui_request":{
  3826   *      "@destination":"IQ",
  3827   *      "@message_id":"UI200809291036128",
  3828   *      "@response_to":"",
  3829   *      "@type":"CHAT-ALIAS",
  3830   *      "alias":{"#text":""}
  3831   *    }
  3832   * }
  3833   */
  3834  ChatAliasRequest.prototype.formatJSON = function() {
  3835      var msg = {
  3836          "ui_request": {
  3837              "@destination":"IS",
  3838              "@type":MESSAGE_TYPES.CHAT_ALIAS,
  3839              "@message_id":utils.getMessageId(),
  3840              "@response_to":"",
  3841              "alias":{
  3842                  "#text":utils.toString(this.alias)
  3843              }
  3844          }
  3845      };
  3846      return JSON.stringify(msg);
  3847  };
  3848  var ChatDispositionRequest = function(uii, agentId, dispositionId, notes, sendAcknowlegement, survey, sessionId) {
  3849      this.uii = uii;
  3850      this.agentId = agentId;
  3851      this.dispositionId = dispositionId;
  3852      this.notes = notes || "";
  3853      this.sendAcknowlegement = sendAcknowlegement || false;
  3854      this.sessionId = sessionId;
  3855      /*
  3856       * survey = {
  3857       *      first_name: {
  3858       *          leadField: "first_name"
  3859       *          value: "Geoff"
  3860       *      },
  3861       *      last_name: {
  3862       *          leadField: "last_name"
  3863       *          value: "Mina"
  3864       *      }
  3865       *      ...
  3866       * }
  3867       */
  3868      this.survey = survey || null;
  3869  };
  3870  /*
  3871   * External Chat:
  3872   * When agent dispositions a chat, send "CHAT-DISPOSITION" request to IntelliQueue
  3873   * {"ui_request":{
  3874   *      "@destination":"IQ",
  3875   *      "@type":"CHAT-DISPOSITION",
  3876   *      "@message_id":"",
  3877   *      "@response_to":"",
  3878   *      "uii":{"#text":""},
  3879   *      "agent_id":{"#text":""},
  3880   *      "session_id" : {"#text" : ""},
  3881   *      "disposition_id":{"#text":""},
  3882   *      "notes":{"#text":"hello"},
  3883   *      "do_ack":{"#text":"true"},
  3884   *      "survey":{
  3885   *          "response":[
  3886   *              {"@extern_id":"text_box","#text":"hello"},
  3887   *              {"@extern_id":"check_box","#text":"20"},
  3888   *              {"@extern_id":"radio_save","#text":"23"}
  3889   *          ]
  3890   *      }
  3891   *    }
  3892   * }
  3893   */
  3894  ChatDispositionRequest.prototype.formatJSON = function() {
  3895      var msg = {
  3896          "ui_request": {
  3897              "@destination":"IQ",
  3898              "@type":MESSAGE_TYPES.CHAT_DISPOSITION,
  3899              "@message_id":utils.getMessageId(),
  3900              "@response_to":"",
  3901              "uii":{
  3902                  "#text":utils.toString(this.uii)
  3903              },
  3904              "agent_id":{
  3905                  "#text":utils.toString(this.agentId)
  3906              },
  3907              "session_id" : {
  3908                "#text" : utils.toString(this.sessionId)
  3909              },
  3910              "disposition_id":{
  3911                  "#text":utils.toString(this.dispositionId)
  3912              },
  3913              "notes":{
  3914                  "#text":utils.toString(this.notes)
  3915              },
  3916              "do_ack":{
  3917                  "#text":this.sendAcknowlegement === true ? "TRUE" : "FALSE"
  3918              }
  3919          }
  3920      };
  3921      /*
  3922       * converts survey to this response
  3923       * survey : {
  3924       *      response: [
  3925       *          { "@extern_id":"", "@lead_update_column":"", "#text":"" }
  3926       *      ]
  3927       * }
  3928       */
  3929      if(this.survey !== null){
  3930          var response = [];
  3931          var keys = Object.keys(this.survey);
  3932          for(var i = 0; i < keys.length; i++){
  3933              var key = keys[i];
  3934              var obj = {
  3935                  "@extern_id": key,
  3936                  "#text": utils.toString(this.survey[key].value)
  3937              };
  3938              response.push(obj);
  3939          }
  3940          msg.ui_request.survey = {"response":response};
  3941      }
  3942      return JSON.stringify(msg);
  3943  };
  3944  var ChatListRequest = function(agentId, monitorAgentId) {
  3945      this.agentId = agentId;
  3946      this.monitorAgentId = monitorAgentId;
  3947  };
  3948  /*
  3949   * External Chat:
  3950   * Requests a list of all chats by monitor agent id
  3951   *
  3952   * {"ui_request":{
  3953   *      "@destination":"IQ",
  3954   *      "@type":"CHAT-LIST",
  3955   *      "@message_id":"",
  3956   *      "@response_to":"",
  3957   *      "agent_id":{"#text":""},
  3958   *      "monitor_agent_id":{"#text":""}
  3959   *    }
  3960   * }
  3961   */
  3962  ChatListRequest.prototype.formatJSON = function() {
  3963      var msg = {
  3964          "ui_request": {
  3965              "@destination":"IQ",
  3966              "@type":MESSAGE_TYPES.CHAT_LIST,
  3967              "@message_id":utils.getMessageId(),
  3968              "@response_to":"",
  3969              "agent_id":{
  3970                  "#text":utils.toString(this.agentId)
  3971              },
  3972              "monitor_agent_id":{
  3973                  "#text":utils.toString(this.monitorAgentId)
  3974              }
  3975          }
  3976      };
  3977      return JSON.stringify(msg);
  3978  };
  3979  /*
  3980   * External Chat:
  3981   * This class is responsible for handling "CHAT-LIST" packets from IntelliQueue.
  3982   *
  3983   *  {
  3984   *      "ui_response":{
  3985   *          "@message_id":"IQ10012016081611595000289",
  3986   *          "@type":"CHAT-LIST",
  3987   *          "@response_to":"",
  3988   *          "agent_id":{"#text":"17"},
  3989   *          "monitor_agent_id":{"#text":"18"},
  3990   *          "chat_list": {}
  3991   *      }
  3992   *  }
  3993   */
  3994  ChatListRequest.prototype.processResponse = function(response) {
  3995      var notif = response.ui_response;
  3996      var model = UIModel.getInstance();
  3997      model.chatListResponse = response;
  3998      return {
  3999          message: "Received CHAT-LIST notification",
  4000          status: "OK",
  4001          messageId: notif['@message_id'],
  4002          agentId: utils.getText(notif, "agent_id"),
  4003          monitorAgentId: utils.getText(notif, "monitor_agent_id"),
  4004          chatList: utils.processResponseCollection( notif, "chat_list", "active_chat")
  4005      };
  4006  };
  4007  var ChatMessageRequest = function(uii, agentId, message, whisper) {
  4008      this.uii = uii;
  4009      this.agentId = agentId;
  4010      this.message = message;
  4011      this.whisper = whisper;
  4012  };
  4013  /*
  4014   * External Chat:
  4015   * When agent submits a chat message, send "CHAT-MESSAGE" request to IntelliQueue
  4016   *
  4017   * {"ui_request":{
  4018   *      "@destination":"IQ",
  4019   *      "@type":"CHAT-MESSAGE",
  4020   *      "@message_id":"",
  4021   *      "@response_to":"",
  4022   *      "uii":{"#text":""},
  4023   *      "agent_id":{"#text":""},
  4024   *      "message":{"#text":"hello"},
  4025   *      "whisper":{"#text":"true|false"}
  4026   *    }
  4027   * }
  4028   */
  4029  ChatMessageRequest.prototype.formatJSON = function() {
  4030      var msg = {
  4031          "ui_request": {
  4032              "@destination":"IQ",
  4033              "@type":MESSAGE_TYPES.CHAT_MESSAGE,
  4034              "@message_id":utils.getMessageId(),
  4035              "@response_to":"",
  4036              "uii":{
  4037                  "#text":utils.toString(this.uii)
  4038              },
  4039              "agent_id":{
  4040                  "#text":utils.toString(this.agentId)
  4041              },
  4042              "message":{
  4043                  "#text":utils.toString(this.message)
  4044              },
  4045              "whisper":{
  4046                  "#text":utils.toString(this.whisper)
  4047              }
  4048          }
  4049      };
  4050      return JSON.stringify(msg);
  4051  };
  4052  /*
  4053   * This class is responsible for handling external CHAT-MESSAGE packets received from
  4054   * IntelliQueue.
  4055   *
  4056   * {"ui_notification":{
  4057   *      "@message_id":"",
  4058   *      "@response_to":"",
  4059   *      "@type":"CHAT-MESSAGE",
  4060   *      "uii":{"#text":""},
  4061   *      "account_id":{"#text":""},
  4062   *      "from":{"#text":""},
  4063   *      "message":{"#text":"hello"},
  4064   *      "dts":{"#text":"2017-05-10 12:40:28"},
  4065   *      "dequeue_agent_id":{"#text":"123"},
  4066   *      "whisper":{"#text":'TRUE'|'FALSE'"}
  4067   *    }
  4068   * }
  4069   */
  4070  ChatMessageRequest.prototype.processResponse = function(response) {
  4071      var resp = response.ui_notification;
  4072      var dts = utils.getText(resp, 'dts').trim();
  4073      var dtsDate = new Date(dts.replace(' ','T'));
  4074      var formattedResponse = {
  4075          uii: utils.getText(resp, 'uii'),
  4076          accountId: utils.getText(resp, 'account_id'),
  4077          from: utils.getText(resp, 'from'),
  4078          type: utils.getText(resp, 'type'),
  4079          message: utils.getText(resp, 'message'),
  4080          whisper: utils.getText(resp, 'whisper'),
  4081          dequeueAgentId: utils.getText(resp, 'dequeue_agent_id'),
  4082          dts: dtsDate,
  4083          mediaLinks :  utils.processResponseCollection(resp, "media_links", "link")
  4084      };
  4085      utils.logMessage(LOG_LEVELS.DEBUG, "New CHAT-MESSAGE packet received from IntelliQueue", response);
  4086      return formattedResponse;
  4087  };
  4088  var ChatPresentedResponseRequest = function(uii, messageId, response, responseReason) {
  4089      this.uii = uii;
  4090      this.messageId = messageId;
  4091      this.response = response;
  4092      this.responseReason = responseReason || "";
  4093  };
  4094  /*
  4095   * External Chat:
  4096   * When Agent receives a CHAT-PRESENTED notification, respond with
  4097   * either ACCEPT or REJECT for presented chat.
  4098   * {"ui_request":{
  4099   *      "@destination":"IQ",
  4100   *      "@type":"CHAT-PRESENTED",
  4101   *      "@message_id":"",
  4102   *      "@response_to":"",
  4103   *      "uii":{"#text":""},
  4104   *      "agent_id":{"#text":""},
  4105   *      "response":{"#text":"ACCEPT|REJECT"},
  4106   *      "response_reason":{"#text":""}
  4107   *    }
  4108   * }
  4109   */
  4110  ChatPresentedResponseRequest.prototype.formatJSON = function() {
  4111      var msg = {
  4112          "ui_request": {
  4113              "@destination":"IQ",
  4114              "@type":MESSAGE_TYPES.CHAT_PRESENTED_RESPONSE,
  4115              "@message_id":utils.getMessageId(),
  4116              "@response_to":this.messageId,
  4117              "uii":{
  4118                  "#text":utils.toString(this.uii)
  4119              },
  4120              "agent_id":{
  4121                  "#text":UIModel.getInstance().agentSettings.agentId
  4122              },
  4123              "response":{
  4124                  "#text":utils.toString(this.response)
  4125              },
  4126              "response_reason":{
  4127                  "#text":utils.toString(this.responseReason)
  4128              }
  4129          }
  4130      };
  4131      return JSON.stringify(msg);
  4132  };
  4133  var ChatRequeueRequest = function(uii, agentId, chatQueueId, skillId, maintainAgent) {
  4134      this.uii = uii;
  4135      this.agentId = agentId;
  4136      this.chatQueueId = chatQueueId;
  4137      this.skillId = skillId || "";
  4138      this.maintainAgent = maintainAgent || false;
  4139  };
  4140  /*
  4141   * External Chat:
  4142   * When agent submits a chat message, send "CHAT-REQUEUE" request to IntelliQueue
  4143   * {"ui_request":{
  4144   *      "@destination":"IQ",
  4145   *      "@type":"CHAT-REQUEUE",
  4146   *      "@message_id":"",
  4147   *      "@response_to":"",
  4148   *      "uii":{"#text":""},
  4149   *      "agent_id":{"#text":""},
  4150   *      "chat_queue_id":{"#text":""},
  4151   *      "skill_id":{"#text":""},
  4152   *      "maintain_agent":{"#text":"true|false"}
  4153   *    }
  4154   * }
  4155   */
  4156  ChatRequeueRequest.prototype.formatJSON = function() {
  4157      var msg = {
  4158          "ui_request": {
  4159              "@destination":"IQ",
  4160              "@type":MESSAGE_TYPES.CHAT_REQUEUE,
  4161              "@message_id":utils.getMessageId(),
  4162              "@response_to":"",
  4163              "uii":{
  4164                  "#text":utils.toString(this.uii)
  4165              },
  4166              "agent_id":{
  4167                  "#text":utils.toString(this.agentId)
  4168              },
  4169              "chat_queue_id":{
  4170                  "#text":utils.toString(this.chatQueueId)
  4171              },
  4172              "skill_id":{
  4173                  "#text":utils.toString(this.skillId)
  4174              },
  4175              "maintain_agent":{
  4176                  "#text":utils.toString(this.maintainAgent)
  4177              }
  4178          }
  4179      };
  4180      return JSON.stringify(msg);
  4181  };
  4182  var ChatRoomRequest = function(action, roomType, roomId, agentOne, agentTwo) {
  4183      this.action = action;
  4184      this.roomType = roomType;
  4185      this.roomId = roomId;
  4186      this.agentOne = agentOne || "";
  4187      this.agentTwo = agentTwo || "";
  4188  };
  4189  /*
  4190   * This class is responsible for sending the packet requesting to either enter
  4191   * a chatroom, or to exit a chatroom to IS. It also handles private chats. There are
  4192   * two possible ways these packets could look:
  4193   *
  4194   * //PUBLIC
  4195   * {"ui_request":{
  4196   *      "@destination":"IS",
  4197   *      "@message_id":"",
  4198   *      "@response_to":"",
  4199   *      "@type":"CHAT-ROOM",
  4200   *      "@room_type":"PUBLIC",
  4201   *      "room_id":{"#text":""},
  4202   *      "action":{"#text":"EXIT|ENTER"}
  4203   *    }
  4204   * }
  4205   * -OR-
  4206   * // PRIVATE
  4207   * {"ui_request":{
  4208   *      "@destination":"IS",
  4209   *      "@message_id":"",
  4210   *      "@response_to":"",
  4211   *      "@type":"CHAT-ROOM",
  4212   *      "@room_type":"PRIVATE",
  4213   *      "agent_one":{"#text":""},
  4214   *      "agent_two":{"#text":""},
  4215   *      "action":{"#text":"ENTER|EXIT"}
  4216   *    }
  4217   * }
  4218   *
  4219   */
  4220  ChatRoomRequest.prototype.formatJSON = function() {
  4221      var msg = {
  4222          "ui_request": {
  4223              "@destination":"IS",
  4224              "@type":MESSAGE_TYPES.CHAT_ROOM,
  4225              "@message_id":utils.getMessageId(),
  4226              "@response_to":"",
  4227              "action":{
  4228                  "#text":utils.toString(this.action)
  4229              }
  4230          }
  4231      };
  4232      if(this.action !== "EXIT"){
  4233          msg.ui_request["@room_type"] = this.roomType;
  4234      }
  4235      if(this.roomType === "PRIVATE" && this.action === "ENTER"){
  4236          msg.ui_request.agent_one = { "#text":utils.toString(this.agentOne) };
  4237          msg.ui_request.agent_two = { "#text":utils.toString(this.agentTwo) };
  4238      }else{
  4239          msg.ui_request.room_id = { "#text":utils.toString(this.roomId) };
  4240      }
  4241      return JSON.stringify(msg);
  4242  };
  4243  var ChatRoomStateRequest = function() {
  4244  };
  4245  /*
  4246   * This class is responsible for processing CHAT-ROOM-STATE packets received
  4247   * from IntelliServices.
  4248   *
  4249   * {"ui_request":{
  4250   *      "@message_id":"",
  4251   *      "@response_to":"",
  4252   *      "@type":"CHAT-ROOM-STATE",
  4253   *      "room_id":{"#text":""},
  4254   *      "agent_id":{"#text":""},
  4255   *      "chat_alias":{"#text":""},
  4256   *      "state":{"#text":""}
  4257   *    }
  4258   * }
  4259   */
  4260  ChatRoomStateRequest.prototype.processResponse = function(response) {
  4261      var resp = response.ui_request;
  4262      var formattedResponse = {
  4263          roomId: utils.getText(resp, 'room_id'),
  4264          agentId: utils.getText(resp, 'agent_id'),
  4265          chatAlias: utils.getText(resp, 'chat_alias'),
  4266          state: utils.getText(resp, 'state')
  4267      };
  4268      utils.logMessage(LOG_LEVELS.DEBUG, "Chat-Room-State update packet received for room #" + formattedResponse.roomId, response);
  4269      return formattedResponse;
  4270  };
  4271  var ChatSendRequest = function(roomId, message) {
  4272      this.roomId = roomId;
  4273      this.message = message;
  4274  };
  4275  /*
  4276   * This class is responsible for creating the CHAT message packet and sending
  4277   * it to IntelliServices.
  4278   *
  4279   * {"ui_request":{
  4280   *      "@destination":"IQ",
  4281   *      "@message_id":"UI200809291036128",
  4282   *      "@response_to":"",
  4283   *      "@type":"CHAT",
  4284   *      "room_id":{"#text":""}
  4285   *      "message":{"#text":""}
  4286   *    }
  4287   * }
  4288   */
  4289  ChatSendRequest.prototype.formatJSON = function() {
  4290      var msg = {
  4291          "ui_request": {
  4292              "@destination":"IS",
  4293              "@type":MESSAGE_TYPES.CHAT_SEND,
  4294              "@message_id":utils.getMessageId(),
  4295              "@response_to":"",
  4296              "room_id":{
  4297                  "#text":utils.toString(this.roomId)
  4298              },
  4299              "message":{
  4300                  "#text":utils.toString(this.message)
  4301              }
  4302          }
  4303      };
  4304      return JSON.stringify(msg);
  4305  };
  4306  /*
  4307   * This class is responsible for handling CHAT packets received from
  4308   * IntelliServices.
  4309   *
  4310   * //PUBLIC
  4311   * {"ui_request":{
  4312   *      "@message_id":"",
  4313   *      "@response_to":"",
  4314   *      "@type":"CHAT",
  4315   *      "room_type":"GROUP",
  4316   *      "room_id":{"#text":""},
  4317   *      "message":{"#text":""},
  4318   *      "sender":{"#text":""},
  4319   *      "sender_id":{"#text":""},
  4320   *      "room_name":{"#text":""}
  4321   *    }
  4322   * }
  4323   * -OR-
  4324   * // PRIVATE
  4325   * {"ui_request":{
  4326   *      "@dynamic_create":"TRUE",
  4327   *      "@message_id":"",
  4328   *      "@response_to":"",
  4329   *      "@type":"CHAT",
  4330   *      "room_type":"PRIVATE",
  4331   *      "room_id":{"#text":""},
  4332   *      "message":{"#text":""},
  4333   *      "sender":{"#text":""},
  4334   *      "room_name":{"#text":""}
  4335   *    }
  4336   * }
  4337   */
  4338  ChatSendRequest.prototype.processResponse = function(response) {
  4339      var resp = response.ui_request;
  4340      var formattedResponse = {
  4341          roomType: utils.getText(resp, 'room_type'),
  4342          roomId: utils.getText(resp, 'room_id'),
  4343          message: utils.getText(resp, 'message'),
  4344          sender: utils.getText(resp, 'sender'),
  4345          senderId: utils.getText(resp, 'sender_id'),
  4346          roomName: utils.getText(resp, 'room_name'),
  4347          dynamicCreate: utils.getText(resp, 'dynamic_create') === "TRUE"
  4348      };
  4349      utils.logMessage(LOG_LEVELS.DEBUG, "New CHAT packet received from IntelliServices", response);
  4350      return formattedResponse;
  4351  };
  4352  var ChatTypingRequest = function(uii,message) {
  4353      this.uii = uii;
  4354      this.message=message;
  4355  };
  4356  /*
  4357   * External Chat:
  4358   * Agent sends typing message to notify client widgets,
  4359   * but the agent's pending message is not sent going this direction.
  4360   * {"ui_request":{
  4361   *      "@destination":"IQ",
  4362   *      "@type":"CHAT-TYPING",
  4363   *      "@message_id":"",
  4364   *      "@response_to":"",
  4365   *      "uii":{"#text":""},
  4366   *      "agent_id":{"#text":""},
  4367   *      "message":{"#text":""}
  4368   *    }
  4369   * }
  4370   */
  4371  ChatTypingRequest.prototype.formatJSON = function() {
  4372      var msg = {
  4373          "ui_request": {
  4374              "@destination":"IQ",
  4375              "@type":MESSAGE_TYPES.CHAT_TYPING,
  4376              "@message_id":utils.getMessageId(),
  4377              "@response_to":"",
  4378              "uii":{
  4379                  "#text":utils.toString(this.uii)
  4380              },
  4381              "agent_id":{
  4382                  "#text":UIModel.getInstance().agentSettings.agentId
  4383              },
  4384              "message":{
  4385                  "#text":utils.toString(this.message)
  4386              }
  4387          }
  4388      };
  4389      return JSON.stringify(msg);
  4390  };
  4391  var LeaveChatRequest = function(uii, agentId, sessionId) {
  4392      this.uii = uii;
  4393      this.agentId = agentId;
  4394      this.sessionId = sessionId;
  4395  };
  4396  /*
  4397   * External Chat:
  4398   * Requests to terminate a chat session on an existing chat uii
  4399   *
  4400   * {"ui_request":{
  4401   *      "@destination":"IQ",
  4402   *      "@type":"CHAT-DROP-SESSION",
  4403   *      "@message_id":"",
  4404   *      "@response_to":"",
  4405   *      "uii":{"#text":""},
  4406   *      "agent_id":{"#text":""},
  4407   *      "session_id":{"#text":""}
  4408   *    }
  4409   * }
  4410   */
  4411  LeaveChatRequest.prototype.formatJSON = function() {
  4412      var msg = {
  4413          "ui_request": {
  4414              "@destination":"IQ",
  4415              "@type":MESSAGE_TYPES.LEAVE_CHAT,
  4416              "@message_id":utils.getMessageId(),
  4417              "@response_to":"",
  4418              "uii":{
  4419                  "#text":utils.toString(this.uii)
  4420              },
  4421              "agent_id":{
  4422                  "#text":UIModel.getInstance().agentSettings.agentId
  4423              },
  4424              "session_id":{
  4425                  "#text":utils.toString(this.sessionId)
  4426              }
  4427          }
  4428      };
  4429      return JSON.stringify(msg);
  4430  };
  4431  var ChatManualSmsRequest = function(agentId, chatQueueId, ani, dnis, message) {
  4432      this.agentId = agentId;
  4433      this.chatQueueId = chatQueueId;
  4434      this.ani = ani;
  4435      this.dnis = dnis;
  4436      this.message = message;
  4437  };
  4438  /*
  4439   * External Chat:
  4440   * When agent submits a manual sms message, send "MANUAL-SMS" request to IntelliQueue
  4441   *
  4442   * {"ui_request":{
  4443   *      "@destination":"IQ",
  4444   *      "@type":"MANUAL-SMS",
  4445   *      "@message_id":"",
  4446   *      "@response_to":"",
  4447   *      "agent_id":{"#text":"1995"},
  4448   *      "chatQueueId":{"#text":"44"},
  4449   *      "ani":{"#text":"1231231234"},
  4450   *      "dnis":{"#text":"5435435432"},
  4451   *      "message":{"#text":"hello"}
  4452   *    }
  4453   * }
  4454   */
  4455  ChatManualSmsRequest.prototype.formatJSON = function() {
  4456      var msg = {
  4457          "ui_request": {
  4458              "@destination":"IQ",
  4459              "@type":MESSAGE_TYPES.CHAT_MANUAL_SMS,
  4460              "@message_id":utils.getMessageId(),
  4461              "@response_to":"",
  4462              "agent_id":{
  4463                  "#text":utils.toString(this.agentId)
  4464              },
  4465              "chat_queue_id":{
  4466                  "#text":utils.toString(this.chatQueueId)
  4467              },
  4468              "ani":{
  4469                  "#text":utils.toString(this.ani)
  4470              },
  4471              "dnis":{
  4472                  "#text":utils.toString(this.dnis)
  4473              },
  4474              "message":{
  4475                  "#text":utils.toString(this.message)
  4476              }
  4477          }
  4478      };
  4479      return JSON.stringify(msg);
  4480  };
  4481  var MonitorChatRequest = function(monitorAgentId) {
  4482      this.monitorAgentId = monitorAgentId;
  4483  };
  4484  /*
  4485   * External Chat:
  4486   * Requests a new session on an existing chat uii
  4487   *
  4488   * {"ui_request":{
  4489   *      "@destination":"IQ",
  4490   *      "@type":"CHAT-MONITOR",
  4491   *      "@message_id":"",
  4492   *      "@response_to":"",
  4493   *      "agent_id":{"#text":""},
  4494   *      "monitor_agent_id":{"#text":""}
  4495   *    }
  4496   * }
  4497   */
  4498  MonitorChatRequest.prototype.formatJSON = function() {
  4499      var msg = {
  4500          "ui_request": {
  4501              "@destination":"IQ",
  4502              "@type":MESSAGE_TYPES.MONITOR_CHAT,
  4503              "@message_id":utils.getMessageId(),
  4504              "@response_to":"",
  4505              "agent_id":{
  4506                  "#text":UIModel.getInstance().agentSettings.agentId
  4507              },
  4508              "monitor_agent_id":{
  4509                  "#text":utils.toString(this.monitorAgentId)
  4510              }
  4511          }
  4512      };
  4513      return JSON.stringify(msg);
  4514  };
  4515  var StopMonitorChatRequest = function(monitorAgentId) {
  4516      this.monitorAgentId = monitorAgentId || "";
  4517  };
  4518  /*
  4519   * External Chat:
  4520   * Requests a termination of a chat monitor session for an agent
  4521   *
  4522   * {"ui_request":{
  4523   *      "@destination":"IQ",
  4524   *      "@type":"CHAT-DROP-MONITORING-SESSION",
  4525   *      "@message_id":"",
  4526   *      "@response_to":"",
  4527   *      "agent_id":{"#text":""},
  4528   *      "monitor_agent_id":{"#text":""}
  4529   *    }
  4530   * }
  4531   */
  4532  StopMonitorChatRequest.prototype.formatJSON = function() {
  4533      var msg = {
  4534          "ui_request": {
  4535              "@destination":"IQ",
  4536              "@type":MESSAGE_TYPES.STOP_MONITOR_CHAT,
  4537              "@message_id":utils.getMessageId(),
  4538              "@response_to":"",
  4539              "agent_id":{
  4540                  "#text":UIModel.getInstance().agentSettings.agentId
  4541              },
  4542              "monitor_agent_id":{
  4543                  "#text":utils.toString(this.monitorAgentId)
  4544              }
  4545          }
  4546      };
  4547      return JSON.stringify(msg);
  4548  };
  4549  /*
  4550   * Process a CHAT-DROP-MONITORING-SESSION notification. Used to notify supervisor monitors that agent has logged out.
  4551   *
  4552   * {"ui_notification":{
  4553   *      "@message_id":"IQ10012016080217135001344",
  4554   *      "@response_to":"",
  4555   *      "@type":"CHAT-DROP-MONITORING-SESSION",
  4556   *      "monitored_agent_id":{"#text":"1"}
  4557   *    }
  4558   * }
  4559   */
  4560  StopMonitorChatRequest.prototype.processResponse = function(data) {
  4561      var notif = data.ui_notification;
  4562      return ({ monitoredAgentId : utils.getText(notif, "monitored_agent_id") });
  4563  };
  4564  var SupervisorListRequest = function() {
  4565  };
  4566  /*
  4567   * This class is responsible for creating a packet to request a list of
  4568   * supervisors from IntelliServices. This is used by the chat function so an
  4569   * agent can grab a list of supervisors and then select one for a private chat.
  4570   *
  4571   * {"ui_request":{
  4572   *      "@destination":"IQ",
  4573   *      "@message_id":"UI200809291036128",
  4574   *      "@response_to":"",
  4575   *      "@type":"SUPERVISOR-LIST",
  4576   *      "agent_id":{"#text":""}
  4577   *    }
  4578   * }
  4579   */
  4580  SupervisorListRequest.prototype.formatJSON = function() {
  4581      var msg = {
  4582          "ui_request": {
  4583              "@destination":"IS",
  4584              "@type":MESSAGE_TYPES.SUPERVISOR_LIST,
  4585              "@message_id":utils.getMessageId(),
  4586              "@response_to":"",
  4587              "agent_id":{
  4588                  "#text":utils.toString(UIModel.getInstance().agentSettings.agentId)
  4589              }
  4590          }
  4591      };
  4592      return JSON.stringify(msg);
  4593  };
  4594  /*
  4595   * This class is responsible for handling the SUPERVISOR-LIST packet
  4596   * rec'd from intelliservices. It will save a copy of this list in the
  4597   * UIModel under a variable called "supervisors". Whenever a new list
  4598   * is rec'd it is overwritten.
  4599   *
  4600   * {"ui_response":{
  4601   *      "@message_id":"IQ982008082910361503344",
  4602   *      "@response_to":"",
  4603   *      "supervisor":[
  4604   *          {"id":{"#text":""}, "fname":{"#text":""}, "lname":{"#text":""}, "uname":{"#text":""} }
  4605   *          {"id":{"#text":""}, "fname":{"#text":""}, "lname":{"#text":""}, "uname":{"#text":""} }
  4606   *      ]
  4607   *    }
  4608   * }
  4609   */
  4610  SupervisorListRequest.prototype.processResponse = function(response) {
  4611      var model = UIModel.getInstance();
  4612      var tempList = utils.processResponseCollection(response, "ui_response", "supervisor");
  4613      var supervisors = [];
  4614      for(var i = 0; i < tempList.length; i++){
  4615          var sup = tempList[i];
  4616          supervisors.push({
  4617              agentId:sup.id,
  4618              firstName:sup.fname,
  4619              lastName:sup.lname,
  4620              username:sup.uname
  4621          });
  4622      }
  4623      utils.logMessage(LOG_LEVELS.DEBUG, "New supervisor list received ", supervisors);
  4624      model.supervisors = supervisors;
  4625      return model.supervisors;
  4626  };
  4627  var ChatClientReconnectNotification = function() {
  4628  };
  4629  /*
  4630   * External Chat:
  4631   * This class is responsible for handling "CHAT-CLIENT-RECONNECT" packets from IntelliQueue.
  4632   * This is sent when a chat connect message is sent to a non-archieved chat.
  4633   *
  4634   *  {
  4635   *      "ui_notification":{
  4636   *          "@message_id":"IQ10012016081611595000289",
  4637   *          "@type":"CHAT-CLIENT-RECONNECT",
  4638   *          "@destination":"IQ",
  4639   *          "@response_to":"",
  4640   *          "account_id":{"#text":"99999999"},
  4641   *          "uii":{"#text":"201608161200240139000000000120"}
  4642   *          "agent_id":{"#text":"1"}
  4643   *      }
  4644   *  }
  4645   */
  4646  ChatClientReconnectNotification.prototype.processResponse = function(notification){
  4647      var notif = notification.ui_notification;
  4648      return {
  4649          message : "Received CHAT-CLIENT-RECONNECT notification",
  4650          status : "OK",
  4651          accountId : utils.getText(notif, "account_id"),
  4652          uii : utils.getText(notif, "uii"),
  4653          agentId : utils.getText(notif, "agent_id")
  4654      };
  4655  };
  4656  var AddChatSessionNotification = function() {
  4657  };
  4658  /*
  4659   * This class is responsible for handling "ADD-CHAT-SESSION" packets from IntelliQueue.
  4660   *
  4661   * {
  4662   *   "ui_notification": {
  4663   *       "@message_id": "IQ982008082918151403727",
  4664   *       "@response_to": "",
  4665   *       "@type": "ADD-CHAT-SESSION",
  4666   *       "session_id": { "#text": "2" },
  4667   *       "uii": { "#text": "200808291814560000000900016558" },
  4668   *       "session_type": { "#text": "AGENT|MONITORING" },
  4669   *       "agent_id": { "#text": "1856" } // null unless monitor type,
  4670   *       "transcript": { }
  4671   *   }
  4672   *  }
  4673   */
  4674  AddChatSessionNotification.prototype.processResponse = function(notification) {
  4675      var notif = notification.ui_notification;
  4676      var formattedResponse = utils.buildDefaultResponse(notification);
  4677      formattedResponse.status = "OK";
  4678      formattedResponse.message = "Received ADD-CHAT-SESSION notification";
  4679      formattedResponse.sessionId = utils.getText(notif, "session_id");
  4680      formattedResponse.uii = utils.getText(notif, "uii");
  4681      formattedResponse.sessionType = utils.getText(notif, "session_type");
  4682      formattedResponse.agentId = utils.getText(notif, "agent_id");
  4683      formattedResponse.transcript = utils.processResponseCollection(notification, 'ui_notification', 'transcript')[0];
  4684      return formattedResponse;
  4685  };
  4686  var ChatActiveNotification = function() {
  4687  };
  4688  /*
  4689   * External Chat:
  4690   * This class is responsible for handling "CHAT-ACTIVE" packets from IntelliQueue.
  4691   * This is sent in response to an agent's CHAT-PRESENTED-RESPONSE accept request.
  4692   *
  4693   *  {
  4694   *      "ui_notification":{
  4695   *          "@message_id":"IQ10012016081611595000289",
  4696   *          "@type":"CHAT-ACTIVE",
  4697   *          "@destination":"IQ",
  4698   *          "@response_to":"",
  4699   *          "account_id":{"#text":"99999999"},
  4700   *          "uii":{"#text":"201608161200240139000000000120"},
  4701   *          "is_monitoring":{"#text":"TRUE"|"FALSE"}
  4702   *      }
  4703   *  }
  4704   */
  4705  ChatActiveNotification.prototype.processResponse = function(notification) {
  4706      var notif = notification.ui_notification;
  4707      return {
  4708          message: "Received CHAT-ACTIVE notification",
  4709          status: "OK",
  4710          accountId: utils.getText(notif, "account_id"),
  4711          uii: utils.getText(notif, "uii"),
  4712          isMonitoring: utils.getText(notif, "is_monitoring")
  4713      };
  4714  };
  4715  var ChatCancelledNotification = function() {
  4716  };
  4717  /*
  4718   * External Chat:
  4719   * This class is responsible for processing "CHAT-CANCELLED" packets from IntelliQueue.
  4720   * If an agent is presented a chat and doesn't respond before the timeout, the CHAT-CANCELLED
  4721   * message is sent from IQ.
  4722   *
  4723   *  {
  4724   *      "ui_notification":{
  4725   *          "@message_id":"IQ10012016081611595000289",
  4726   *          "@type":"CHAT-CANCELLED",
  4727   *          "@destination":"IQ",
  4728   *          "@response_to":"",
  4729   *          "account_id":{"#text":"99999999"},
  4730   *          "uii":{"#text":"201608161200240139000000000120"}
  4731   *      }
  4732   *  }
  4733   */
  4734  ChatCancelledNotification.prototype.processResponse = function(notification) {
  4735      var notif = notification.ui_notification;
  4736      return {
  4737          message: "Received CHAT-CANCELLED notification",
  4738          status: "OK",
  4739          messageId: notif['@message_id'],
  4740          accountId: utils.getText(notif, "account_id"),
  4741          uii: utils.getText(notif, "uii")
  4742      };
  4743  };
  4744  var ChatInactiveNotification = function() {
  4745  };
  4746  /*
  4747   * External Chat:
  4748   * This class is responsible for handling "CHAT-INACTIVE" packets from IntelliQueue.
  4749   * This is sent to the agent when the last session is disconnected from a chat.
  4750   *
  4751   *  {
  4752   *      "ui_notification":{
  4753   *          "@message_id":"IQ10012016081611595000289",
  4754   *          "@type":"CHAT-INACTIVE",
  4755   *          "@destination":"IQ",
  4756   *          "@response_to":"",
  4757   *          "account_id":{"#text":"99999999"},
  4758   *          "uii":{"#text":"201608161200240139000000000120"},
  4759   *          "disposition_timeout":{"#text":"30"},
  4760   *          "dequeue_agent_id":{"#text":"123"}
  4761   *      }
  4762   *  }
  4763   */
  4764  ChatInactiveNotification.prototype.processResponse = function(notification) {
  4765      var notif = notification.ui_notification;
  4766      return {
  4767          message: "Received CHAT-INACTIVE notification",
  4768          status: "OK",
  4769          accountId: utils.getText(notif, "account_id"),
  4770          uii: utils.getText(notif, "uii"),
  4771          dispositionTimeout: utils.getText(notif, "disposition_timeout"),
  4772          dequeueAgentId: utils.getText(notif, "dequeue_agent_id")
  4773      };
  4774  };
  4775  var ChatPresentedNotification = function() {
  4776  };
  4777  /*
  4778   * External Chat:
  4779   * This class is responsible for handling "CHAT-PRESENTED" packets from IntelliQueue.
  4780   * When this notification is received, the Agent can either Accept or Decline which will
  4781   * be sent back to IntelliQueue as a CHAT-PRESENTED-RESPONSE.
  4782   *
  4783   *  {
  4784   *      "ui_notification":{
  4785   *          "@message_id":"IQ10012016081611595000289",
  4786   *          "@type":"CHAT-PRESENTED",
  4787   *          "@destination":"IQ",
  4788   *          "@response_to":"",
  4789   *          "chat_queue_id":{"#text":"3"},
  4790   *          "chat_queue_name":{"#text":"Support Chat"},
  4791   *          "account_id":{"#text":"99999999"},
  4792   *          "uii":{"#text":"201608161200240139000000000120"},
  4793   *          "channel_type":{"#text":""},
  4794   *          "allow_accept":{"#text":"TRUE|FALSE"}
  4795   *      }
  4796   *  }
  4797   */
  4798  ChatPresentedNotification.prototype.processResponse = function(notification) {
  4799      var notif = notification.ui_notification;
  4800      return {
  4801          message: "Received CHAT-PRESENTED notification",
  4802          status: "OK",
  4803          messageId: notif['@message_id'],
  4804          accountId: utils.getText(notif, "account_id"),
  4805          uii: utils.getText(notif, "uii"),
  4806          channelType: utils.getText(notif, "channel_type"),
  4807          chatQueueId: utils.getText(notif, "chat_queue_id"),
  4808          chatQueueName: utils.getText(notif, "chat_queue_name"),
  4809          allowAccept: utils.getText(notif, "allow_accept")
  4810      };
  4811  };
  4812  var ChatTypingNotification = function() {
  4813  };
  4814  /*
  4815   * External Chat:
  4816   * This class is responsible for handling "CHAT-TYPING" packets from IntelliQueue.
  4817   * When this notification is received, the AgentUI will show the pending message
  4818   * so far from the client chat widget and typing notification.
  4819   *
  4820   *  {
  4821   *      "ui_notification":{
  4822   *          "@message_id":"IQ10012016081611595000289",
  4823   *          "@type":"CHAT-TYPING",
  4824   *          "@destination":"IQ",
  4825   *          "@response_to":"",
  4826   *          "uii":{"#text":"201608161200240139000000000120"},
  4827   *          "account_id":{"#text":"99999999"},
  4828   *          "from":{"#text":""},
  4829   *          "message":{"#text":"this is the message before actual send"}
  4830   *          "dequeue_agent_id":{"#text":"123"}
  4831   *      }
  4832   *  }
  4833   */
  4834  ChatTypingNotification.prototype.processResponse = function(notification) {
  4835      var notif = notification.ui_notification;
  4836      return {
  4837          message: "Received CHAT-TYPING notification",
  4838          status: "OK",
  4839          accountId: utils.getText(notif, "account_id"),
  4840          uii: utils.getText(notif, "uii"),
  4841          from: utils.getText(notif, "from"),
  4842          type: utils.getText(notif, "type"),
  4843          pendingMessage: utils.getText(notif, "message"),
  4844          dequeueAgentId: utils.getText(notif, "dequeue_agent_id")
  4845      };
  4846  };
  4847  var NewChatNotification = function() {
  4848  };
  4849  /*
  4850   * External Chat:
  4851   * This class is responsible for handling "NEW-CHAT" packets from IntelliQueue.
  4852   *
  4853   *  {
  4854   *      "ui_notification":{
  4855   *          "@message_id":"IQ10012016081611595000289",
  4856   *          "@type":"NEW-CHAT",
  4857   *          "@destination":"IQ",
  4858   *          "@response_to":"",
  4859   *          "uii":{"#text":"201608161200240139000000000120"},
  4860   *          "account_id":{"#text":"99999999"},
  4861   *          "session_id":{"#text":"2"},
  4862   *          "agent_id":{"#text":"1180958"},
  4863   *          "queue_dts":{"#text":""},
  4864   *          "queue_time":{"#text":""},
  4865   *          "chat_queue_id":{"#text":""},
  4866   *          "chat_queue_name":{"#text":""},
  4867   *          "chat_requeue_type" : {"#text":""}
  4868   *          "app_url":{"#text":""},
  4869   *          "channel_type":{"#text":""},
  4870   *          "ani":{"#text":""},
  4871   *          "dnis":{"#text":""},
  4872   *          "survey_pop_type":{"#text":""},
  4873   *          "script_id":{"#text":""},
  4874   *          "script_version":{"#text":""},
  4875   *          "idle_timeout":{"#text":""},
  4876   *          "is_monitoring":{#text":"TRUE"|"FALSE"},
  4877   *          "monitored_agent_id":{"#text":"123"| ""} <-- only populated if is_monitoring == TRUE
  4878   *          "requeue_shortcuts":{
  4879   *              "requeue_shortcut":{
  4880   *                  "@chat_queue_id":"2",
  4881   *                  "@name":"test queue",
  4882   *                  "@skill_id":""
  4883   *              }
  4884   *          },
  4885   *          "chat_dispositions":{
  4886   *              "disposition":[
  4887   *                  { "@disposition_id":"2", "@is_success":"true", "@is_complete":"false", "@is_default"="0", "@email_template_id":"1", "#text":"Complete"},
  4888   *                  { "@disposition_id":"3", "@is_success":"true", "@is_complete":"false", "@is_default"="0", "#text":"Requeue"}
  4889   *              ]
  4890   *          },
  4891   *          "chat_requeue_shortcuts" :{
  4892   *              shortcut : [
  4893   *                {@chat_requeue_shortcut_id:"3", @name:"test", @rank:"1",@requeue_chat_queue_id:"74",@skill_id:""}
  4894   *              ]
  4895   *          }
  4896   *          "transcript":{
  4897   *              "message":[
  4898   *                  { "@from":"system", "@type":"SYSTEM", "@whisper":"FALSE", "@dts":"yyyy-MM-dd HH:mm:ss", "#text":"User1 connected"},
  4899   *                  { "@from":"dlbooks", "@type":"AGENT", "@whisper":"FALSE", "@dts":"yyyy-MM-dd HH:mm:ss", "#text":"Hello"},
  4900   *                  { "@from":"user1", "@type":"CLIENT", "@whisper":"FALSE", "@dts":"yyyy-MM-dd HH:mm:ss", "#text":"Hi"}
  4901   *              ]
  4902   *          },
  4903   *          "json_baggage":{"#text":"json_string_form_data"}, <--- pre-form chat data
  4904   *      }
  4905   *  }
  4906   */
  4907  NewChatNotification.prototype.processResponse = function(notification) {
  4908      var notif = notification.ui_notification;
  4909      var dts = utils.getText(notif,'queue_dts');
  4910      dts = new Date(dts.replace(' ','T'));
  4911      // set up new call obj
  4912      var newChat = {
  4913          uii: utils.getText(notif,'uii'),
  4914          accountId: utils.getText(notif,'account_id'),
  4915          sessionId: utils.getText(notif,'session_id'),
  4916          agentId: utils.getText(notif,'agent_id'),
  4917          queueDts: dts,
  4918          queueTime: utils.getText(notif,'queue_time'),
  4919          chatQueueId: utils.getText(notif,'chat_queue_id'),
  4920          chatQueueName: utils.getText(notif,'chat_queue_name'),
  4921          chatRequeueType : utils.getText(notif, 'chat_requeue_type'),
  4922          appUrl: utils.getText(notif,'app_url'),
  4923          channelType: utils.getText(notif,'channel_type'),
  4924          ani: utils.getText(notif,'ani'),
  4925          dnis: utils.getText(notif,'dnis'),
  4926          surveyPopType: utils.getText(notif,'survey_pop_type'),
  4927          scriptId: utils.getText(notif,'script_id'),
  4928          scriptVersion: utils.getText(notif,'script_version'),
  4929          idleTimeout: utils.getText(notif,'idle_timeout'),
  4930          isMonitoring: utils.getText(notif,'is_monitoring'),
  4931          monitoredAgentId: utils.getText(notif,'monitored_agent_id'),
  4932          preChatData: utils.getText(notif,'json_baggage')
  4933      };
  4934      newChat.requeueShortcuts = utils.processResponseCollection(notification, 'ui_notification', 'chat_requeue_shortcuts', 'shortcut')[0];
  4935      newChat.chatDispositions = utils.processResponseCollection(notification, 'ui_notification', 'chat_dispositions', 'disposition')[0];
  4936      newChat.transcript = utils.processResponseCollection(notification, 'ui_notification', 'transcript', 'message')[0];
  4937      newChat.baggage = utils.processResponseCollection(notification, 'ui_notification', 'json_baggage')[0];
  4938      if(newChat.chatDispositions && newChat.chatDispositions.disposition){
  4939          newChat.chatDispositions.dispositions = [newChat.chatDispositions]
  4940      }else{
  4941          newChat.chatDispositions = newChat.chatDispositions.dispositions;
  4942      }
  4943      if(newChat.transcript && newChat.transcript.message){
  4944          newChat.transcript = [newChat.transcript];
  4945      }else{
  4946          newChat.transcript = newChat.transcript.messages;
  4947      }
  4948      if(newChat.preChatData){
  4949          try {
  4950              newChat.preChatData = JSON.parse(newChat.preChatData);
  4951          }catch(err){
  4952              utils.logMessage(LOG_LEVELS.ERROR, "Error parsing the pre-form chat data.", notif);
  4953          }
  4954      }
  4955      // convert numbers to boolean
  4956      if(newChat.chatDispositions){
  4957          for(var d = 0; d < newChat.chatDispositions.length; d++){
  4958              var disp = newChat.chatDispositions[d];
  4959              disp.isComplete = disp.isComplete === "1";
  4960              disp.isSuccess = disp.isSuccess === "1";
  4961              disp.isDefault = disp.isDefault === "1";
  4962          }
  4963      }
  4964      // convert dates
  4965      if(newChat.transcript){
  4966          for(var t = 0; t < newChat.transcript.length; t++){
  4967              var msg = newChat.transcript[t];
  4968              if(msg.dts){
  4969                  msg.dts = new Date(msg.dts.replace(' ','T'));
  4970              }
  4971          }
  4972      }
  4973      // Build token map
  4974      newChat.baggage = buildChatTokenMap(notif, newChat);
  4975      return newChat;
  4976  };
  4977  function buildChatTokenMap(notif, newChat){
  4978      var tokens = {};
  4979      var model = UIModel.getInstance();
  4980      if(newChat.preChatData){
  4981          for(var prop in newChat.preChatData){
  4982              if(newChat.preChatData.hasOwnProperty(prop)){
  4983                  tokens[prop] = newChat.preChatData[prop];
  4984              }
  4985          }
  4986      }
  4987      try{
  4988          tokens["chatQueueId"] = newChat.chatQueueId;
  4989          tokens["chatQueueName"] = newChat.chatQueueName;
  4990          tokens["ani"] = newChat.ani;
  4991          tokens["dnis"] = newChat.dnis;
  4992          tokens["uii"] = newChat.uii;
  4993      }catch(any){
  4994          console.error("There was an error parsing chat tokens for basic chat info. ", any);
  4995      }
  4996      try{
  4997          tokens["agentFirstName"] = model.agentSettings.firstName;
  4998          tokens["agentLastName"] = model.agentSettings.lastName;
  4999          tokens["agentExternalId"] = model.agentSettings.externalAgentId;
  5000          tokens["agentType"] = model.agentSettings.agentType;
  5001          tokens["agentEmail"] = model.agentSettings.email;
  5002          tokens["agentUserName"] = model.agentSettings.username;
  5003      }catch(any){
  5004          console.error("There was an error parsing chat tokens for agent info. ", any);
  5005      }
  5006      return tokens;
  5007  }
  5008  var AgentStats = function() {
  5009  };
  5010  /*
  5011   * This class is responsible for handling an Agent Stats packet rec'd from IntelliServices.
  5012   * It will save a copy of it in the UIModel. Could be a single agent or array of agents.
  5013   *
  5014    {"ui_stats":{
  5015         "@type":"AGENT",
  5016         "agent":{
  5017             "@alt":"INBOUND",
  5018             "@atype":"AGENT",
  5019             "@avgtt":"00.0",
  5020             "@calls":"0",
  5021             "@da":"0",
  5022             "@droute":"6789050673",
  5023             "@f":"John",
  5024             "@gdesc":"",
  5025             "@gname":"",
  5026             "@id":"1856",
  5027             "@l":"Doe",
  5028             "@ldur":"6",
  5029             "@ltype":"INBOUND",
  5030             "@oh":"0",
  5031             "@pd":"0",
  5032             "@pdt":"0",
  5033             "@pres":"0",
  5034             "@rna":"0",
  5035             "@sdur":"6",
  5036             "@sp":"",
  5037             "@state":"AVAILABLE",
  5038             "@ttt":"0",
  5039             "@u":"jdoe",
  5040             "@uii":"",
  5041             "@util":"0.00",
  5042             "@call_duration:0"
  5043         }
  5044       }
  5045    }
  5046   */
  5047  AgentStats.prototype.processResponse = function(stats) {
  5048      var resp = stats.ui_stats.agent;
  5049      var agentStats = [];
  5050      if (!Array.isArray(resp)) {
  5051          resp = [resp];
  5052      }
  5053      try {
  5054          for (var i = 0; i < resp.length; i++) {
  5055              agentStats.push({
  5056                  agentLoginType: resp[i]["@alt"],
  5057                  agentType: resp[i]["@atype"],
  5058                  avgTalkTime: resp[i]["@avgtt"],
  5059                  calls: resp[i]["@calls"],
  5060                  isDequeueAgent: resp[i]["@da"],
  5061                  defaultRoute: resp[i]["@droute"],
  5062                  firstName: resp[i]["@f"],
  5063                  queueDesc: resp[i]["@gdesc"],
  5064                  queueName: resp[i]["@gname"],
  5065                  agentId: resp[i]["@id"],
  5066                  lastName: resp[i]["@l"],
  5067                  loginDuration: resp[i]["@ldur"],
  5068                  loginType: resp[i]["@ltype"],
  5069                  offHook: resp[i]["@oh"],
  5070                  pendingDisp: resp[i]["@pd"],
  5071                  pendingDispTime: resp[i]["@pdt"],
  5072                  presented: resp[i]["@pres"],
  5073                  rna: resp[i]["@rna"],
  5074                  stateDuration: resp[i]["@sdur"],
  5075                  skillProfileName: resp[i]["@sp"],
  5076                  agentState: resp[i]["@state"],
  5077                  totalTalkTime: resp[i]["@ttt"],
  5078                  username: resp[i]["@u"],
  5079                  uii: resp[i]["@uii"],
  5080                  utilization: resp[i]["@util"],
  5081                  callDuration: resp[i]["@call_duration"]
  5082              });
  5083          }
  5084      } catch(e) {
  5085      }
  5086      UIModel.getInstance().agentStats = agentStats;
  5087      return agentStats;
  5088  };
  5089  var AgentDailyStats = function() {
  5090  };
  5091  /*
  5092   * This class is responsible for handling an Agent Daily Stats packet rec'd from IntelliServices.
  5093   * It will save a copy of it in the UIModel.
  5094   *
  5095   * {"ui_stats":{
  5096   *      "@type":"AGENTDAILY",
  5097   *      "agent_id":{"#text":"1180723"},
  5098   *      "total_login_sessions":{"#text":"1"},
  5099   *      "total_calls_handled":{"#text":"0"},
  5100   *      "total_preview_dials":{"#text":"0"},
  5101   *      "total_manual_dials":{"#text":"0"},
  5102   *      "total_rna":{"#text":"0"},
  5103   *      "total_talk_time":{"#text":"0"},
  5104   *      "total_offhook_time":{"#text":"0"},
  5105   *      "total_login_time":{"#text":"7808"},
  5106   *      "total_success_dispositions":{"#text":"0"}
  5107   *    }
  5108   * }
  5109   */
  5110  AgentDailyStats.prototype.processResponse = function(stats) {
  5111      var model = UIModel.getInstance().agentDailyStats;
  5112      var resp = stats.ui_stats;
  5113      model.agentId = utils.getText(resp, "agent_id");
  5114      model.totalLoginSessions = utils.getText(resp, "total_login_sessions");
  5115      model.totalChatsHandled = utils.getText(resp, "total_chats_handled");
  5116      model.totalCallsHandled = utils.getText(resp, "total_calls_handled");
  5117      model.totalPreviewDials = utils.getText(resp, "total_preview_dials");
  5118      model.totalManualDials = utils.getText(resp, "total_manual_dials");
  5119      model.totalRna = utils.getText(resp, "total_rna");
  5120      model.totalSuccessDispositions = utils.getText(resp, "total_success_dispositions");
  5121      if(!model.totalTalkTime) {
  5122          // init daily stats to first stats packet if they don't exist
  5123          model.totalLoginTime = utils.getText(resp, "total_login_time");
  5124          model.totalOffhookTime = utils.getText(resp, "total_offhook_time");
  5125          model.totalTalkTime = utils.getText(resp, "total_talk_time");
  5126          model.currCallTime = "0";
  5127      }
  5128      return model;
  5129  };
  5130  var CampaignStats = function() {
  5131  };
  5132  /*
  5133   * This class is responsible for handling a Campaign Stats packet rec'd from IntelliServices.
  5134   * It will save a copy of it in the UIModel.
  5135   *
  5136   * {"ui_stats":{
  5137   *      "@type":"CAMPAIGN",
  5138   *      "campaign":[
  5139   *          {
  5140   *              "@a":"0","@aba":"0","@an":"0","@av":"0","@b":"0","@c":"1","@e":"0","@f":"0",
  5141   *              "@id":"60275","@int":"0","@m":"0","@na":"0","@name":"Test Campaign",
  5142   *              "@p":"0","@r":"1","@s":"0","@tc":"0","@ttt":"0"
  5143   *          },
  5144   *          {
  5145   *              "@a":"0","@aba":"0","@an":"0","@av":"0","@b":"0","@c":"0","@e":"0","@f":"0",
  5146   *              "@id":"60293","@int":"0","@m":"0","@na":"0","@name":"Test Campaign w\\ Search",
  5147   *              "@p":"0","@r":"19","@s":"0","@tc":"0","@ttt":"0"
  5148   *          }
  5149   *     ],
  5150   *     "totals":{
  5151   *          "noanswer":{"#text":"0"},
  5152   *          "totalConnects":{"#text":"0"},
  5153   *          "pending":{"#text":"0"},
  5154   *          "active":{"#text":"0"},
  5155   *          "error":{"#text":"0"},
  5156   *          "totalTalkTime":{"#text":"0"},
  5157   *          "answer":{"#text":"0"},
  5158   *          "abandon":{"#text":"0"},
  5159   *          "ready":{"#text":"20"},
  5160   *          "machine":{"#text":"0"},
  5161   *          "intercept":{"#text":"0"},
  5162   *          "busy":{"#text":"0"},
  5163   *          "complete":{"#text":"1"},
  5164   *          "fax":{"#text":"0"}
  5165   *     }
  5166   *   }
  5167   * }
  5168   */
  5169  CampaignStats.prototype.processResponse = function(stats) {
  5170      var resp = stats.ui_stats;
  5171      var totals = utils.processResponseCollection(stats,"ui_stats","totals")[0];
  5172      var campaigns = [];
  5173      var campRaw = null;
  5174      if (!Array.isArray(resp.campaign)) {
  5175          resp.campaign = [resp.campaign];
  5176      }
  5177      for(var c = 0; c < resp.campaign.length; c++){
  5178          campRaw = resp.campaign[c];
  5179          if (campRaw == null) {
  5180              continue;
  5181          }
  5182          campaigns.push({
  5183              active:campRaw["@a"],
  5184              abandon:campRaw["@aba"],
  5185              answer:campRaw["@an"],
  5186              available:campRaw["@av"],
  5187              busy:campRaw["@b"],
  5188              complete:campRaw["@c"],
  5189              error:campRaw["@e"],
  5190              fax:campRaw["@f"],
  5191              campaignId:campRaw["@id"],
  5192              intercept:campRaw["@int"],
  5193              machine:campRaw["@m"],
  5194              noanswer:campRaw["@na"],
  5195              campaignName:campRaw["@name"],
  5196              pending:campRaw["@p"],
  5197              ready:campRaw["@r"],
  5198              staffed:campRaw["@s"],
  5199              totalConnects:campRaw["@tc"],
  5200              totalTalkTime:campRaw["@ttt"]
  5201          });
  5202      }
  5203      var campaignStats = {
  5204          type: resp["@type"],
  5205          campaigns: campaigns,
  5206          totals:totals
  5207      };
  5208      UIModel.getInstance().campaignStats = campaignStats;
  5209      return campaignStats;
  5210  };
  5211  var ChatQueueStats = function() {
  5212  };
  5213  /*
  5214   * This class is responsible for handling an Chat Stats packet rec'd from IntelliServices.
  5215   * It will save a copy of it in the UIModel.
  5216   *
  5217   *{
  5218   *  "ui_stats": {
  5219   *  "@type": "CHAT",
  5220   *  "chatQueue": [
  5221   *      {
  5222   *          "@active": "1",
  5223   *          "@available": "0",
  5224   *          "@avgAbandon": "00.0",
  5225   *          "@avgChatTime": "00.0",
  5226   *          "@avgQueueTime": "00.0",
  5227   *          "@chatQueueId": "1",
  5228   *          "@chatQueueName": "testing chat quuee",
  5229   *          "@deflected": "0",
  5230   *          "@inQueue": "0",
  5231   *          "@longestInQueue": "0",
  5232   *          "@presented": "0",
  5233   *          "@routing": "0",
  5234   *          "@staffed": "0",
  5235   *          "@totalAbandonTime": "0",
  5236   *          "@totalAnswerTime": "0",
  5237   *          "@totalChatTime": "0",
  5238   *          "@totalQueueTime": "0",
  5239   *          "@utilization": "00.0"
  5240   *      },
  5241   *      {
  5242   *          "@active": "0",
  5243   *          "@available": "0",
  5244   *          "@avgAbandon": "00.0",
  5245   *          "@avgChatTime": "00.0",
  5246   *          "@avgQueueTime": "00.0",
  5247   *          "@chatQueueId": "3",
  5248   *          "@chatQueueName": "testing test",
  5249   *          "@deflected": "0",
  5250   *          "@inQueue": "0",
  5251   *          "@longestInQueue": "0",
  5252   *          "@presented": "0",
  5253   *          "@routing": "0",
  5254   *          "@staffed": "0",
  5255   *          "@totalAbandonTime": "0",
  5256   *          "@totalAnswerTime": "0",
  5257   *          "@totalChatTime": "0",
  5258   *          "@totalQueueTime": "0",
  5259   *          "@utilization": "00.0"
  5260   *      }
  5261   *  ],
  5262   *  "totals": {
  5263   *      "routing": {"#text": "0"},
  5264   *      "ttotalAnswerTime": {"#text": "0"},
  5265   *      "inQueue": { "#text": "0"},
  5266   *      "ttotalChatTime": {"#text": "0"},
  5267   *      "ttotalAbandonTime": {"#text": "0"},
  5268   *      "presented": {"#text": "0},
  5269   *      "accepted": {"#text": "0"},
  5270   *      "deflected": {"#text": "0"},
  5271   *      "active": {"#text": "1"},
  5272   *      "abandoned": {"#text": "0"},
  5273   *      "ttotalQueueTime": {"#text": "0"}
  5274   *   }
  5275   *  }
  5276   *}
  5277   */
  5278  ChatQueueStats.prototype.processResponse = function(stats) {
  5279      var resp = stats.ui_stats;
  5280      var totals = utils.processResponseCollection(stats,"ui_stats","totals")[0];
  5281      var chatQueues = utils.processResponseCollection(stats,"ui_stats","chatQueue");
  5282      var chatQueueStats = {
  5283          type:resp["@type"],
  5284          chatQueues: chatQueues,
  5285          totals:totals
  5286      };
  5287      UIModel.getInstance().chatQueueStats = chatQueueStats;
  5288      return chatQueueStats;
  5289  };
  5290  var QueueStats = function() {
  5291  };
  5292  /*
  5293   * This class is responsible for handling an Queue Stats packet rec'd from IntelliServices.
  5294   * It will save a copy of it in the UIModel.
  5295   *
  5296   * {
  5297   *   "ui_stats":{
  5298   *       "@type":"GATE",
  5299   *       "gate":{
  5300   *           "@aba":"0","@active":"0","@ans":"0","@asa":"00.0","@avail":"2",
  5301   *           "@avga":"00.0","@avgq":"00.0","@avgt":"00.0","@def":"0","@id":"12126",
  5302   *           "@inq":"0","@long_c":"0","@longq":"0","@name":"Cris inbound",
  5303   *           "@pres":"0","@route":"0","@short_aba":"0","@short_c":"0","@sla":"100.0",
  5304   *           "@sla_f":"0","@sla_p":"0","@staff":"2","@t_aba":"0","@t_q":"0","@t_soa":"0","@util":"00.0"
  5305   *       },
  5306   *       "totals":{
  5307   *           "inQueue":{"#text":"0"},
  5308   *           "answered":{"#text":"0"},
  5309   *           "totalABATime":{"#text":"0"},
  5310   *           "active":{"#text":"0"},
  5311   *           "longCall":{"#text":"0"},
  5312   *           "shortCall":{"#text":"0"},
  5313   *           "slaPass":{"#text":"0"},
  5314   *           "totalQueueTime":{"#text":"0"},
  5315   *           "routing":{"#text":"0"},
  5316   *           "totalTalkTime":{"#text":"0"},
  5317   *           "shortAbandon":{"#text":"0"},
  5318   *           "presented":{"#text":"0"},
  5319   *           "totalSOA":{"#text":"0"},
  5320   *           "slaFail":{"#text":"0"},
  5321   *           "deflected":{"#text":"0"},
  5322   *           "abandoned":{"#text":"0"}
  5323   *      }
  5324   *   }
  5325   * }
  5326   */
  5327  QueueStats.prototype.processResponse = function(stats) {
  5328      var resp = stats.ui_stats;
  5329      var totals = utils.processResponseCollection(stats,"ui_stats","totals")[0];
  5330      var queues = [];
  5331      var gateRaw = {};
  5332      if (!Array.isArray(resp.gate)) {
  5333          resp.gate = [resp.gate];
  5334      }
  5335      for(var c = 0; c < resp.gate.length; c++) {
  5336          gateRaw = resp.gate[c];
  5337          if (gateRaw == null) {
  5338              continue;
  5339          }
  5340          queues.push({
  5341              abandon: gateRaw["@aba"],
  5342              active: gateRaw["@active"],
  5343              answer: gateRaw["@ans"],
  5344              asa: gateRaw["@asa"],
  5345              available: gateRaw["@avail"],
  5346              avgAbandon: gateRaw["@avga"],
  5347              avgQueue: gateRaw["@avgq"],
  5348              avgTalk: gateRaw["@avgt"],
  5349              deflected: gateRaw["@def"],
  5350              queueId: gateRaw["@id"],
  5351              inQueue: gateRaw["@inq"],
  5352              longCall: gateRaw["@long_c"],
  5353              longestInQueue: gateRaw["@longq"],
  5354              queueName: gateRaw["@name"],
  5355              presented: gateRaw["@pres"],
  5356              routing: gateRaw["@route"],
  5357              shortAbandon: gateRaw["@short_aba"],
  5358              shortCall: gateRaw["@short_c"],
  5359              sla: gateRaw["@sla"],
  5360              slaPass: gateRaw["@sla_p"],
  5361              slaFail: gateRaw["@sla_f"],
  5362              staffed: gateRaw["@staff"],
  5363              tAbandonTime: gateRaw["@t_aba"],
  5364              tQueueTime: gateRaw["@t_q"],
  5365              tSpeedOfAnswer: gateRaw["@t_soa"],
  5366              utilization: gateRaw["@util"]
  5367          });
  5368      }
  5369      var queueStats = {
  5370          type:resp["@type"],
  5371          queues: queues,
  5372          totals:totals
  5373      };
  5374      UIModel.getInstance().queueStats = queueStats;
  5375      return queueStats;
  5376  };
  5377  var UIModel = (function() {
  5378      var instance;
  5379      function init() {
  5380          // Singleton
  5381          // Private methods and variables here //
  5382          //function privateMethod(){
  5383          //    console.log( "I am private" );
  5384          //}
  5385          //
  5386          //var privateVariable = "I'm also private";
  5387          // Public methods and variables
  5388          return {
  5389              currentCall: {},                        // save the NEW-CALL notification in parsed form
  5390              pendingNewCallSessions: {},             // save any pending call sessions, in case the new call packet hasn't arrived
  5391              callTokens:{},                          // Stores a map of all tokens for a call
  5392              callbacks:[],
  5393              libraryInstance: null,                  // Initialized to the library instance on startup
  5394              pingIntervalId: null,                   // The id of the timer used to send ping-call messages
  5395              statsIntervalId: null,                  // The id of the timer used to send stats request messages
  5396              agentDailyIntervalId: null,             // The id of the timer used to update some agent daily stats values
  5397              waitingForAddSession : null,
  5398              // internal chat requests
  5399              chatAliasRequest : null,
  5400              chatRoomRequest : null,
  5401              chatSendRequest : null,
  5402              supervisorListRequest : null,
  5403              chatRoomStateRequest : new ChatRoomStateRequest(),
  5404              // external chat requests/notifications
  5405              chatActiveNotification : new ChatActiveNotification(),
  5406              chatInactiveNotification : new ChatInactiveNotification(),
  5407              chatDispositionRequest : null,
  5408              chatMessageRequest : new ChatMessageRequest(),
  5409              chatPresentedNotification : new ChatPresentedNotification(),
  5410              chatPresentedRequest : null,
  5411              chatRequeueRequest : null,
  5412              chatTypingNotification : new ChatTypingNotification(),
  5413              chatTypingRequest : null,
  5414              newChatNotification : new NewChatNotification(),
  5415              chatClientReconnectNotification : new ChatClientReconnectNotification(),
  5416              // request instances
  5417              agentStateRequest : null,
  5418              chatStateRequest : null,
  5419              ackRequest : new AckRequest(),
  5420              bargeInRequest : null,
  5421              callNotesRequest : null,
  5422              callbacksPendingRequest : null,
  5423              campaignDispositionsRequest : null,
  5424              configRequest : null,
  5425              coldXferRequest : null,
  5426              dispositionRequest : null,
  5427              dispositionManualPassRequest : null,
  5428              hangupRequest : null,
  5429              holdRequest : null,
  5430              leadHistoryRequest : null,
  5431              leadInsertRequest : null,
  5432              leadUpdateRequest : null,
  5433              logoutRequest : null,
  5434              loginRequest : null,                // Original LoginRequest sent to IS - used for reconnects
  5435              offhookInitRequest : null,
  5436              offhookTermRequest : null,
  5437              oneToOneOutdialRequest : null,
  5438              oneToOneOutdialCancelRequest : null,
  5439              pauseRecordRequest : null,
  5440              pingCallRequest : null,
  5441              previewDialRequest : null,
  5442              reconnectRequest : null,
  5443              recordRequest : null,
  5444              requeueRequest : null,
  5445              statsRequest : null,
  5446              tcpaSafeRequest : null,
  5447              warmXferRequest : null,
  5448              warmXferCancelRequest : null,
  5449              chatListRequest: null,
  5450              directAgentTransferListRequest: null,
  5451              directAgentTransferRequest: null,
  5452              // response packets
  5453              agentStatePacket : null,
  5454              chatStatePacket : null,
  5455              configPacket : null,
  5456              currentCallPacket : null,
  5457              loginPacket : null,
  5458              offhookInitPacket : null,
  5459              offhookTermPacket : null,
  5460              transferSessions: {},
  5461              chatListResponse : null,
  5462              // notification packets
  5463              addSessionNotification: new AddSessionNotification(),
  5464              dialGroupChangeNotification : new DialGroupChangeNotification(),
  5465              dialGroupChangePendingNotification : new DialGroupChangePendingNotification(),
  5466              dropSessionNotification: new DropSessionNotification(),
  5467              earlyUiiNotification: new EarlyUiiNotification(),
  5468              endCallNotification : new EndCallNotification(),
  5469              gatesChangeNotification : new GatesChangeNotification(),
  5470              genericNotification : new GenericNotification(),
  5471              newCallNotification: new NewCallNotification(),
  5472              // stats packets
  5473              agentStatsPacket: new AgentStats(),
  5474              agentDailyStatsPacket: new AgentDailyStats(),
  5475              queueStatsPacket: new QueueStats(),
  5476              campaignStatsPacket: new CampaignStats(),
  5477              chatQueueStatsPacket: new ChatQueueStats(),
  5478              // application state
  5479              applicationSettings : {
  5480                  availableCountries : [],
  5481                  isLoggedInIS : false,               // a check for whether or not user is logged in with IntelliServices
  5482                  socketConnected : false,
  5483                  socketDest : "",
  5484                  isTcpaSafeMode : false             // Comes in at the account-level - will get set to true if this interface should be in tcpa-safe-mode only.
  5485              },
  5486              // stat objects
  5487              agentStats:[],
  5488              agentDailyStats: {},
  5489              campaignStats:{},
  5490              queueStats:{},
  5491              chatQueueStats:{},
  5492              // current agent settings
  5493              agentSettings : {
  5494                  accountId: null,                    // account agent belongs to
  5495                  agentId : 0,
  5496                  agentType : "AGENT",                // AGENT | SUPERVISOR
  5497                  altDefaultLoginDest : "",
  5498                  availableAgentStates : [],
  5499                  callerIds : [],
  5500                  callState: null,                     // display the current state of the call
  5501                  currentState : "OFFLINE",           // Agent system/base state
  5502                  currentStateLabel : "",             // Agent aux state label
  5503                  defaultLoginDest : "",
  5504                  dialDest : "",                      // Destination agent is logged in with for offhook session, set on configure response, if multi values in format "xxxx|,,xxxx"
  5505                  email : "",
  5506                  externalAgentId : "",
  5507                  firstName : "",
  5508                  guid: "",                           // unique key generated on login, used for accessing spring endpoints
  5509                  isLoggedIn : false,                 // agent is logged in to the platform
  5510                  isOffhook : false,                  // track whether or not the agent has an active offhook session
  5511                  isMonitoring : false,               // track whether or not the offhook session is for monitoring
  5512                  initLoginState : "AVAILABLE",       // state agent is placed in on successful login
  5513                  initLoginStateLabel : "Available",  // state label for agent on successful login
  5514                  isOutboundPrepay : false,           // determines if agent is a prepay agent
  5515                  lastName : "",
  5516                  loginDTS : null,                    // date and time of the final login phase (IQ)
  5517                  loginType : "NO-SELECTION",         // Could be INBOUND | OUTBOUND | BLENDED | NO-SELECTION, set on login response
  5518                  maxBreakTime : -1,
  5519                  maxLunchTime : -1,
  5520                  onCall : false,                     // true if agent is on an active call
  5521                  onManualOutdial : false,            // true if agent is on a manual outdial call
  5522                  outboundManualDefaultRingtime : "30",
  5523                  pendingCallbacks : [],
  5524                  pendingDialGroupChange: 0,          // Set to Dial Group Id if we are waiting to change dial groups until agent ends call
  5525                  phoneLoginPin: "",
  5526                  realAgentType : "AGENT",
  5527                  supervisors : [],                   // Used for agent chat
  5528                  totalCalls : 0,                     // Call counter that is incremented every time a new session is received
  5529                  transferNumber : "",                // May be pre-populated by an external interface, if so, the transfer functionality uses it
  5530                  updateDGFromAdminUI : false,        // if pending Dial Group change came from AdminUI, set to true (only used if request is pending)
  5531                  updateLoginMode : false,            // gets set to true when doing an update login (for events control)
  5532                  username : "",                      // Agent's username
  5533                  wasMonitoring : false               // used to track if the last call was a monitoring call
  5534              },
  5535              // current agent permissions
  5536              agentPermissions : {
  5537                  allowBlended : true,                // Controls whether or not the agent can log into both inbound queues and an outbound dialgroup
  5538                  allowCallControl : true,            // Set from the the login response packet
  5539                  allowChat : false,                  // Controls whether or not the agent has the option to open the Chat Queue Manager
  5540                  allowCrossQueueRequeue : false,     // Controls whether or not the agent can requeue to a different queue group
  5541                  allowInbound : true,                // Controls whether or not the agent can log into an inbound queue
  5542                  allowLeadInserts : false,           // Controls whether or not the agents can insert leads
  5543                  allowLeadSearch : false,            // Controlled by the dial-group allow_lead_search setting. Enables or disables the lead search
  5544                  allowLoginControl : true,           // Controls whether or not the agent can log in
  5545                  allowLoginUpdates : true,           // Controls whether or not the agent can update their login
  5546                  allowManualCalls : true,            // Controls whether or not the agents have the option to make a manual outbound call
  5547                  allowManualPass : true,             // Controls whether or not the agent has the option to make a manual pass on a lead
  5548                  allowManualIntlCalls : false,       // Controls whether or not the agent has the option to make international manual outbound calls
  5549                  allowManualOutboundGates : false,   // Controls whether or not the agent has the option to select queues to convert manual outbound calls to
  5550                  allowOffHook : true,                // Controls whether or not the agents can go offhook
  5551                  allowOutbound : true,               // Controls whether or not the agent can log into an outdial group
  5552                  allowPreviewLeadFilters : false,    // Controlled by the dial-group allow_preview_lead_filters setting. Enables or disables the filters on the preview style forms
  5553                  allowLeadUpdatesByCampaign : {},    // For each campaign ID, store whether leads can be updated
  5554                  disableSupervisorMonitoring : true, // Controls whether or not a supervisor can view agent stats
  5555                  progressiveEnabled : false,         // Preview dial feature that enables auto-calls from the preview window.
  5556                  requireFetchedLeadsCalled : false,  // Controlled by the dial-group require_fetched_leads_called setting. Enables or disables the requirement to only fetch new leads when current leads are called or expired. ONly for Preview or TCPA-SAFE.
  5557                  showLeadHistory : true              // Controls whether or not the agents can view lead history
  5558              },
  5559              // chat
  5560              chatSettings :{
  5561                  availableChatQueues : [],           // List of all chat queues agent has access to, set on login
  5562                  availableChatRooms : [],            // List of all chat rooms agent has access to, set on login
  5563                  chatQueues : [],                    // Array of chat queues agent is signed into
  5564                  alias : ""                          // Chat alias, on-login this is the UID, but is changed if the user changes it
  5565              },
  5566              // connection objects
  5567              connectionSettings : {
  5568                  hashCode : null,                    // used specifically for reconnects
  5569                  reconnect : false                   // variable tracks the type of login, on init it's false...once connected it's set to true
  5570              },
  5571              // inbound settings
  5572              inboundSettings : {
  5573                  availableQueues : [],               // array of queues agent has access to, set on login
  5574                  availableSkillProfiles : [],        // array of skill profiles agent has access to, set on login
  5575                  queues : [],                        // array of queues agent is signed into, set on config response
  5576                  skillProfile : {}                   // The skill profile the agent is signed into, set on config response
  5577              },
  5578              // outbound settings
  5579              outboundSettings : {
  5580                  availableCampaigns : [],            // array of campaigns agent has access to, set on login
  5581                  availableOutdialGroups : [],        // array of dial groups agent has access to, set on login
  5582                  insertCampaigns : [],
  5583                  defaultDialGroup: 0,
  5584                  outdialGroup : {},                  // dial group agent is signed into
  5585                  previewDialLeads : [],              // list of leads returned from preview dial request
  5586                  tcpaSafeLeads : [],                 // list of leads returned from tcpa safe request
  5587                  campaignDispositions : []           // list of campaign dispositions for specific campaign
  5588              },
  5589              scriptSettings : {
  5590                  availableScripts : [],              // array of all scripts associated with any campaigns or queues agent is logged into
  5591                  loadedScripts: {}                   // stores script data by script id e.g. {1:{}, 32:{}}
  5592              },
  5593              // Public methods
  5594              incrementTotalCalls: function() {
  5595                  this.agentSettings.totalCalls = this.agentSettings.totalCalls + 1;
  5596              }
  5597          };
  5598      }
  5599      return {
  5600          // Get the Singleton instance if one exists
  5601          // or create one if it doesn't
  5602          getInstance: function () {
  5603              if (!instance) {
  5604                  instance = init();
  5605              }
  5606              return instance;
  5607          },
  5608          resetInstance: function () {
  5609              instance = null;
  5610          }
  5611      };
  5612  })();
  5613  function NewCallUtils(instance, data) {
  5614      this.instance = instance;
  5615      this.data = data;
  5616      var that = this;
  5617      this.setupAddSessionCallback = function() {
  5618          var sessionUii = utils.getText(data.ui_notification, "uii"),
  5619              sessionId = utils.getText(data.ui_notification, "session_id"),
  5620              call = UIModel.getInstance().currentCall;
  5621          if(call.uii === sessionUii) {
  5622              // we already have a new call packet for this session
  5623              _delayedAddSessionCallback(that.instance, that.data);
  5624          } else {
  5625              // uii mismatch, but call has been dispositioned
  5626              UIModel.getInstance().pendingNewCallSessions[sessionUii] = UIModel.getInstance().pendingNewCallSessions[sessionUii] || {};
  5627              UIModel.getInstance().pendingNewCallSessions[sessionUii][sessionId] = that;
  5628          }
  5629      };
  5630      this.processSessionsForCall = function() {
  5631          var uii = UIModel.getInstance().currentCall.uii,
  5632              delayedSessions = UIModel.getInstance().pendingNewCallSessions[uii];
  5633          if(delayedSessions && Object.keys(delayedSessions).length > 0) {
  5634              // we have delayed sessions to process
  5635              for(var sessionId in delayedSessions) {
  5636                  if(delayedSessions.hasOwnProperty(sessionId)) {
  5637                      var session = delayedSessions[sessionId];
  5638                      _delayedAddSessionCallback(session.instance, session.data);
  5639                  } else {
  5640                      console.error('error processing sessions for uii: ' + uii + ' session: ' + sessionId );
  5641                  }
  5642              }
  5643              delete UIModel.getInstance().pendingNewCallSessions[uii];
  5644          }
  5645      };
  5646      function _delayedAddSessionCallback(instance, data) {
  5647          var addSessionNotif = new AddSessionNotification();
  5648          var addResponse = addSessionNotif.processResponse(data);
  5649          utils.fireCallback(instance, CALLBACK_TYPES.ADD_SESSION, addResponse);
  5650      }
  5651  }
  5652  var utils = {
  5653      logMessage: function(logLevel, message, data){
  5654          var instance = UIModel.getInstance().libraryInstance;
  5655          if(instance._db){
  5656              var transaction = instance._db.transaction(["logger"], "readwrite");
  5657              var store = transaction.objectStore("logger");
  5658              var record = {
  5659                  logLevel: logLevel,
  5660                  message: message,
  5661                  dts: new Date(),
  5662                  data: data
  5663              };
  5664              var request = store.add(record);
  5665          }else{
  5666              //console.log("AgentLibrary: indexedDb not available");
  5667          }
  5668      },
  5669      sendMessage: function(instance, msg) {
  5670          var msgObj = JSON.parse(msg);
  5671          if (instance.socket && instance.socket.readyState === 1) {
  5672              // add message id to request map, then send message
  5673              var type = msgObj.ui_request['@type'];
  5674              var destination = msgObj.ui_request['@destination'];
  5675              var message = "Sending " + type + " request message to " + destination;
  5676              instance._requests.push({ id: msgObj.ui_request['@message_id'], type: msgObj.ui_request['@type'], msg: msgObj.ui_request });
  5677              // keep rolling window of latest 1000 requests
  5678              if(instance._requests.length > 1000){
  5679                  instance._requests.shift();
  5680              }
  5681              instance.socket.send(msg);
  5682              if(type === 'STATS'){
  5683                  utils.logMessage(LOG_LEVELS.STATS, message, msgObj);
  5684              }else{
  5685                  utils.logMessage(LOG_LEVELS.INFO, message, msgObj);
  5686              }
  5687          } else {
  5688              // add message to queue if socket is not open.
  5689              instance._queuedMsgs.push({dts: new Date(), msg: msg});
  5690          }
  5691      },
  5692      processResponse: function(instance, response)
  5693      {
  5694          var type = response.ui_response['@type'];
  5695          var messageId = response.ui_response['@message_id'];
  5696          var dest = (messageId === "" || !messageId) ? "IS" : messageId.slice(0, 2);
  5697          var message = "Received " + type.toUpperCase() + " response message from " + dest;
  5698          // log message response
  5699          utils.logMessage(LOG_LEVELS.INFO, message, response);
  5700          // Send generic on message response
  5701          utils.fireCallback(instance, CALLBACK_TYPES.ON_MESSAGE, response);
  5702          // Fire callback function
  5703          switch (type.toUpperCase()) {
  5704              case MESSAGE_TYPES.AGENT_STATE:
  5705                  if (UIModel.getInstance().agentStateRequest === null) {
  5706                      UIModel.getInstance().agentStateRequest = new AgentStateRequest(response.ui_response.current_state["#text"], response.ui_response.agent_aux_state['#text']);
  5707                  }
  5708                  var stateChangeResponse = UIModel.getInstance().agentStateRequest.processResponse(response);
  5709                  utils.fireCallback(instance, CALLBACK_TYPES.AGENT_STATE, stateChangeResponse);
  5710                  break;
  5711              case MESSAGE_TYPES.BARGE_IN:
  5712                  var resp = UIModel.getInstance().bargeInRequest.processResponse(response);
  5713                  var responseTo = response.ui_response['@response_to'];
  5714                  var request = utils.findRequestById(instance, responseTo);
  5715                  if (request) {
  5716                      // found corresponding request, fire registered callback for type
  5717                      var audioState = request.msg.audio_state['#text'];
  5718                      if (audioState === "MUTE") {
  5719                          utils.fireCallback(instance, CALLBACK_TYPES.SILENT_MONITOR, resp);
  5720                      } else if (audioState === "COACHING") {
  5721                          utils.fireCallback(instance, CALLBACK_TYPES.COACH_CALL, resp);
  5722                      } else {
  5723                          utils.fireCallback(instance, CALLBACK_TYPES.BARGE_IN, resp);
  5724                      }
  5725                  } else {
  5726                      // no corresponding request, just fire FULL audio type BARGE-IN callback
  5727                      utils.fireCallback(instance, CALLBACK_TYPES.BARGE_IN, resp);
  5728                  }
  5729                  break;
  5730              case MESSAGE_TYPES.CAMPAIGN_DISPOSITIONS:
  5731                  var campaignDispsResposne = UIModel.getInstance().campaignDispositionsRequest.processResponse(response);
  5732                  utils.fireCallback(instance, CALLBACK_TYPES.CAMPAIGN_DISPOSITIONS, campaignDispsResposne);
  5733                  break;
  5734              case MESSAGE_TYPES.CALL_NOTES:
  5735                  var callNotes = UIModel.getInstance().callNotesRequest.processResponse(response);
  5736                  utils.fireCallback(instance, CALLBACK_TYPES.CALL_NOTES, callNotes);
  5737                  break;
  5738              case MESSAGE_TYPES.CALLBACK_PENDING:
  5739                  var pendingCallbacks = UIModel.getInstance().callbacksPendingRequest.processResponse(response);
  5740                  utils.fireCallback(instance, CALLBACK_TYPES.CALLBACK_PENDING, pendingCallbacks);
  5741                  break;
  5742              case MESSAGE_TYPES.HOLD:
  5743                  var holdRequest;
  5744                  if(UIModel.getInstance().holdRequest === null){
  5745                      holdRequest = new HoldRequest();
  5746                  }else{
  5747                      holdRequest = UIModel.getInstance().holdRequest;
  5748                  }
  5749                  var hold = holdRequest.processResponse(response);
  5750                  utils.fireCallback(instance, CALLBACK_TYPES.HOLD, hold);
  5751                  break;
  5752              case MESSAGE_TYPES.LEAD_HISTORY:
  5753                  var history = UIModel.getInstance().leadHistoryRequest.processResponse(response);
  5754                  utils.fireCallback(instance, CALLBACK_TYPES.LEAD_HISTORY, history);
  5755                  break;
  5756              case MESSAGE_TYPES.LEAD_INSERT:
  5757                  var insert = UIModel.getInstance().leadInsertRequest.processResponse(response);
  5758                  utils.fireCallback(instance, CALLBACK_TYPES.LEAD_INSERT, insert);
  5759                  break;
  5760              case MESSAGE_TYPES.LEAD_UPDATE:
  5761                  var update = UIModel.getInstance().leadUpdateRequest.processResponse(response);
  5762                  utils.fireCallback(instance, CALLBACK_TYPES.LEAD_UPDATE, update);
  5763                  break;
  5764              case MESSAGE_TYPES.LOGIN:
  5765                  if (dest === "IS") {
  5766                      var loginResponse = UIModel.getInstance().loginRequest.processResponse(response);
  5767                      utils.fireCallback(instance, CALLBACK_TYPES.LOGIN, loginResponse);
  5768                  } else if (dest === 'IQ') {
  5769                      var configResponse = UIModel.getInstance().configRequest.processResponse(response);
  5770                      utils.fireCallback(instance, CALLBACK_TYPES.CONFIG, configResponse);
  5771                  }
  5772                  break;
  5773              case MESSAGE_TYPES.LOGOUT:
  5774                  // TODO add processResponse?
  5775                  utils.fireCallback(instance, CALLBACK_TYPES.LOGOUT, response);
  5776                  break;
  5777              case MESSAGE_TYPES.OFFHOOK_INIT:
  5778                  var offhook = new OffhookInitRequest();
  5779                  var initResponse = offhook.processResponse(response);
  5780                  utils.fireCallback(instance, CALLBACK_TYPES.OFFHOOK_INIT, initResponse);
  5781                  break;
  5782              case MESSAGE_TYPES.PAUSE_RECORD:
  5783                  var pauseRequest;
  5784                  if(UIModel.getInstance().pauseRecordRequest === null){
  5785                      pauseRequest = new PauseRecordRequest();
  5786                  }else{
  5787                      pauseRequest = UIModel.getInstance().pauseRecordRequest;
  5788                  }
  5789                  var pauseRec = pauseRequest.processResponse(response);
  5790                  utils.fireCallback(instance, CALLBACK_TYPES.PAUSE_RECORD, pauseRec);
  5791                  break;
  5792              case MESSAGE_TYPES.RECORD:
  5793                  var record = UIModel.getInstance().recordRequest.processResponse(response);
  5794                  utils.fireCallback(instance, CALLBACK_TYPES.RECORD, record);
  5795                  break;
  5796              case MESSAGE_TYPES.REQUEUE:
  5797                  var requeue = UIModel.getInstance().requeueRequest.processResponse(response);
  5798                  utils.fireCallback(instance, CALLBACK_TYPES.REQUEUE, requeue);
  5799                  break;
  5800              case MESSAGE_TYPES.SUPERVISOR_LIST:
  5801                  var supervisorList = UIModel.getInstance().supervisorListRequest.processResponse(response);
  5802                  utils.fireCallback(instance, CALLBACK_TYPES.SUPERVISOR_LIST, supervisorList);
  5803                  break;
  5804              case MESSAGE_TYPES.SCRIPT_CONFIG:
  5805                  var script = UIModel.getInstance().scriptConfigRequest.processResponse(response);
  5806                  utils.fireCallback(instance, CALLBACK_TYPES.SCRIPT_CONFIG, script);
  5807                  break;
  5808              case MESSAGE_TYPES.XFER_COLD:
  5809                  var coldXfer = UIModel.getInstance().coldXferRequest.processResponse(response);
  5810                  utils.fireCallback(instance, CALLBACK_TYPES.XFER_COLD, coldXfer);
  5811                  break;
  5812              case MESSAGE_TYPES.XFER_WARM:
  5813                  var warmXfer = UIModel.getInstance().warmXferRequest.processResponse(response);
  5814                  utils.fireCallback(instance, CALLBACK_TYPES.XFER_WARM, warmXfer);
  5815                  break;
  5816              case MESSAGE_TYPES.XFER_WARM_CANCEL:
  5817                  var warmXferCancel = UIModel.getInstance().warmXferCancelRequest.processResponse(response);
  5818                  utils.fireCallback(instance, CALLBACK_TYPES.XFER_WARM_CANCEL, warmXferCancel);
  5819                  break;
  5820              case MESSAGE_TYPES.ACK:
  5821                  var ack = UIModel.getInstance().ackRequest.processResponse(response);
  5822                  var responseTo = response.ui_response['@response_to'];
  5823                  var request = utils.findRequestById(instance, responseTo);
  5824                  ack.uii = request.msg.uii && request.msg.uii["#text"];
  5825                  utils.fireCallback(instance, CALLBACK_TYPES.ACK, ack);
  5826                  break;
  5827              case MESSAGE_TYPES.CHAT_LIST:
  5828                  var chatList = new ChatListRequest();
  5829                  var chatListResponse = chatList.processResponse(response);
  5830                  utils.fireCallback(instance, CALLBACK_TYPES.CHAT_LIST, chatListResponse);
  5831                  break;
  5832              case MESSAGE_TYPES.CHAT_STATE:
  5833                  var chatState = new ChatStateRequest();
  5834                  var chatStateResponse = chatState.processResponse(response);
  5835                  utils.fireCallback(instance, CALLBACK_TYPES.CHAT_STATE, chatStateResponse);
  5836                  break;
  5837              case MESSAGE_TYPES.DIRECT_AGENT_TRANSFER_LIST:
  5838                  var agentList = new DirectAgentTransferList();
  5839                  var agentListResponse = agentList.processResponse(response);
  5840                  utils.fireCallback(instance, CALLBACK_TYPES.DIRECT_AGENT_TRANSFER_LIST, agentListResponse);
  5841                  break;
  5842              case MESSAGE_TYPES.DIRECT_AGENT_TRANSFER:
  5843                  var agentXfer = new DirectAgentTransfer();
  5844                  var agentXferResponse = agentXfer.processResponse(response);
  5845                  utils.fireCallback(instance, CALLBACK_TYPES.DIRECT_AGENT_TRANSFER, agentXferResponse);
  5846                  break;
  5847          }
  5848      },
  5849      processNotification: function(instance, data) {
  5850          var type = data.ui_notification['@type'];
  5851          var messageId = data.ui_notification['@message_id'];
  5852          var dest = messageId === "" ? "IS" : messageId.slice(0, 2);
  5853          var message = "Received " + type.toUpperCase() + " notification message from " + dest;
  5854          // log message response
  5855          utils.logMessage(LOG_LEVELS.INFO, message, data);
  5856          switch (type.toUpperCase()){
  5857              case MESSAGE_TYPES.ADD_SESSION:
  5858                  new NewCallUtils(instance, data).setupAddSessionCallback();
  5859                  break;
  5860              case MESSAGE_TYPES.DIAL_GROUP_CHANGE:
  5861                  var dgChangeNotif = new DialGroupChangeNotification();
  5862                  var changeResponse = dgChangeNotif.processResponse(data);
  5863                  utils.fireCallback(instance, CALLBACK_TYPES.DIAL_GROUP_CHANGE, changeResponse);
  5864                  break;
  5865              case MESSAGE_TYPES.DIAL_GROUP_CHANGE_PENDING:
  5866                  var dgChangePendNotif = new DialGroupChangePendingNotification();
  5867                  var pendResponse = dgChangePendNotif.processResponse(data);
  5868                  utils.fireCallback(instance, CALLBACK_TYPES.DIAL_GROUP_CHANGE_PENDING, pendResponse);
  5869                  break;
  5870              case MESSAGE_TYPES.DROP_SESSION:
  5871                  var dropSesNotif = new DropSessionNotification(instance);
  5872                  var dropSesResponse = dropSesNotif.processResponse(data);
  5873                  utils.fireCallback(instance, CALLBACK_TYPES.DROP_SESSION, dropSesResponse);
  5874                  break;
  5875              case MESSAGE_TYPES.EARLY_UII:
  5876                  var earlyUiiNotif = new EarlyUiiNotification(instance);
  5877                  var earlyUiiResponse = earlyUiiNotif.processResponse(data);
  5878                  utils.fireCallback(instance, CALLBACK_TYPES.EARLY_UII, earlyUiiResponse);
  5879                  break;
  5880              case MESSAGE_TYPES.END_CALL:
  5881                  var endCallNotif = new EndCallNotification(instance);
  5882                  var endCallResponse = endCallNotif.processResponse(data);
  5883                  utils.fireCallback(instance, CALLBACK_TYPES.END_CALL, endCallResponse);
  5884                  break;
  5885              case MESSAGE_TYPES.GATES_CHANGE:
  5886                  var gateChangeNotif = new GatesChangeNotification();
  5887                  var gateChangeResponse = gateChangeNotif.processResponse(data);
  5888                  utils.fireCallback(instance, CALLBACK_TYPES.GATES_CHANGE, gateChangeResponse);
  5889                  break;
  5890              case MESSAGE_TYPES.GENERIC:
  5891                  var genericNotif = new GenericNotification();
  5892                  var generic = genericNotif.processResponse(data);
  5893                  var responseTo = data.ui_notification['@response_to'];
  5894                  var request = utils.findRequestById(instance, responseTo);
  5895                  if(request){
  5896                      // found corresponding request, fire registered callback for type
  5897                      var type = request.type;
  5898                      var callbackFnName = utils.findCallbackBasedOnMessageType(type);
  5899                      if(callbackFnName){
  5900                          if(type === MESSAGE_TYPES.CALLBACK_CANCEL){
  5901                              generic.leadId = request.msg.lead_id["#text"];
  5902                          }
  5903                          utils.fireCallback(instance, callbackFnName, generic);
  5904                      }else{
  5905                          // no registered callback, fallback to generic notification
  5906                          utils.fireCallback(instance, CALLBACK_TYPES.GENERIC_NOTIFICATION, generic);
  5907                      }
  5908                  }else{
  5909                      if(generic.messageCode === "001") {
  5910                          // caller hangup, stop pinging call
  5911                          if(UIModel.getInstance().pingIntervalId){
  5912                              clearInterval(UIModel.getInstance().pingIntervalId);
  5913                          }
  5914                      }
  5915                      // no corresponding request, just fire generic notification callback
  5916                      utils.fireCallback(instance, CALLBACK_TYPES.GENERIC_NOTIFICATION, generic);
  5917                  }
  5918                  break;
  5919              case MESSAGE_TYPES.NEW_CALL:
  5920                  var newCallNotif = new NewCallNotification();
  5921                  var newCallResponse = newCallNotif.processResponse(data);
  5922                  utils.fireCallback(instance, CALLBACK_TYPES.NEW_CALL, newCallResponse);
  5923                  new NewCallUtils(instance, data).processSessionsForCall();
  5924                  break;
  5925              case MESSAGE_TYPES.OFFHOOK_TERM:
  5926                  if(UIModel.getInstance().offhookTermRequest === null){
  5927                      // offhook term initiated by IQ
  5928                      UIModel.getInstance().offhookTermRequest = new OffhookTermRequest();
  5929                  }
  5930                  var termResponse = UIModel.getInstance().offhookTermRequest.processResponse(data);
  5931                  utils.fireCallback(instance, CALLBACK_TYPES.OFFHOOK_TERM, termResponse);
  5932                  break;
  5933              case MESSAGE_TYPES.PREVIEW_LEAD_STATE:
  5934                  var leadStateNotif = new PreviewLeadStateNotification();
  5935                  var leadStateResponse = leadStateNotif.processResponse(data);
  5936                  utils.fireCallback(instance, CALLBACK_TYPES.PREVIEW_LEAD_STATE, leadStateResponse);
  5937                  break;
  5938              case MESSAGE_TYPES.PENDING_DISP:
  5939                  var pendingDispNotif = new PendingDispNotification();
  5940                  var pendingDispResponse = pendingDispNotif.processResponse(data);
  5941                  utils.fireCallback(instance, CALLBACK_TYPES.PENDING_DISP, pendingDispResponse);
  5942                  break;
  5943              case MESSAGE_TYPES.PENDING_CHAT_DISP:
  5944                  var pendingChatDispNotif = new PendingChatDispNotification();
  5945                  var pendingChatDispResponse = pendingChatDispNotif.processResponse(data);
  5946                  utils.fireCallback(instance, CALLBACK_TYPES.PENDING_CHAT_DISP, pendingChatDispResponse);
  5947                  break;
  5948              case MESSAGE_TYPES.REVERSE_MATCH:
  5949                  var reverseMatchNotif = new ReverseMatchNotification();
  5950                  var reverseMatchResponse = reverseMatchNotif.processResponse(data);
  5951                  utils.fireCallback(instance, CALLBACK_TYPES.REVERSE_MATCH, reverseMatchResponse);
  5952                  break;
  5953              case MESSAGE_TYPES.TCPA_SAFE_LEAD_STATE:
  5954                  var leadStateTcpaNotif = new TcpaSafeLeadStateNotification();
  5955                  var leadStateTcpaResponse = leadStateTcpaNotif.processResponse(data);
  5956                  utils.fireCallback(instance, CALLBACK_TYPES.TCPA_SAFE_LEAD_STATE, leadStateTcpaResponse);
  5957                  break;
  5958              case MESSAGE_TYPES.CHAT_ACTIVE:
  5959                  var activeNotif = new ChatActiveNotification();
  5960                  var activeResponse = activeNotif.processResponse(data);
  5961                  utils.fireCallback(instance, CALLBACK_TYPES.CHAT_ACTIVE, activeResponse);
  5962                  break;
  5963              case MESSAGE_TYPES.CHAT_INACTIVE:
  5964                  var inactiveNotif = new ChatInactiveNotification();
  5965                  var inactiveResponse = inactiveNotif.processResponse(data);
  5966                  utils.fireCallback(instance, CALLBACK_TYPES.CHAT_INACTIVE, inactiveResponse);
  5967                  break;
  5968              case MESSAGE_TYPES.CHAT_CLIENT_RECONNECT :
  5969                  var reconnectNotif = new ChatClientReconnectNotification();
  5970                  var reconnectResponse = reconnectNotif.processResponse(data);
  5971                  utils.fireCallback(instance, CALLBACK_TYPES.CHAT_CLIENT_RECONNECT, reconnectResponse);
  5972                  break;
  5973              case MESSAGE_TYPES.CHAT_PRESENTED:
  5974                  var presentedNotif = new ChatPresentedNotification();
  5975                  var presentedResponse = presentedNotif.processResponse(data);
  5976                  utils.fireCallback(instance, CALLBACK_TYPES.CHAT_PRESENTED, presentedResponse);
  5977                  break;
  5978              case MESSAGE_TYPES.CHAT_TYPING:
  5979                  var typingNotif = new ChatTypingNotification();
  5980                  var typingResponse = typingNotif.processResponse(data);
  5981                  utils.fireCallback(instance, CALLBACK_TYPES.CHAT_TYPING, typingResponse);
  5982                  break;
  5983              case MESSAGE_TYPES.CHAT_NEW:
  5984                  var newChatNotif = new NewChatNotification();
  5985                  var newChatResponse = newChatNotif.processResponse(data);
  5986                  utils.fireCallback(instance, CALLBACK_TYPES.CHAT_NEW, newChatResponse);
  5987                  break;
  5988              case MESSAGE_TYPES.CHAT_MESSAGE:
  5989                  var chatMessage = new ChatMessageRequest();
  5990                  var chatMessageResponse = chatMessage.processResponse(data);
  5991                  utils.fireCallback(instance, CALLBACK_TYPES.CHAT_MESSAGE, chatMessageResponse);
  5992                  break;
  5993              case MESSAGE_TYPES.CHAT_CANCELLED:
  5994                  var chatCancelled = new ChatCancelledNotification();
  5995                  var chatCancelledResponse = chatCancelled.processResponse(data);
  5996                  utils.fireCallback(instance, CALLBACK_TYPES.CHAT_CANCELLED, chatCancelledResponse);
  5997                  break;
  5998              case MESSAGE_TYPES.CHAT_ADD_SESSION:
  5999                  var addChatSession = new AddChatSessionNotification();
  6000                  var addChatSessionResponse = addChatSession.processResponse(data);
  6001                  utils.fireCallback(instance, CALLBACK_TYPES.CHAT_ADD_SESSION, addChatSessionResponse);
  6002                  break;
  6003              case MESSAGE_TYPES.STOP_MONITOR_CHAT:
  6004                  var stopChatMonitor = new StopMonitorChatRequest();
  6005                  var stopChatMonitorResponse = stopChatMonitor.processResponse(data);
  6006                  utils.fireCallback(instance, CALLBACK_TYPES.CHAT_STOP_MONITOR, stopChatMonitorResponse);
  6007                  break;
  6008              case MESSAGE_TYPES.DIRECT_AGENT_ROUTE:
  6009                  var directAgentTransfer = new DirectAgentTransferNotification();
  6010                  var directAgentTransferResponse = directAgentTransfer.processResponse(data);
  6011                  utils.fireCallback(instance, CALLBACK_TYPES.DIRECT_AGENT_TRANSFER_NOTIF, directAgentTransferResponse);
  6012                  break;
  6013              case MESSAGE_TYPES.AGENT_DEBUG_EMAIL:
  6014                  var emailNotif = new AdminDebugEmailNotification();
  6015                  var emailNotifResp = emailNotif.processResponse(data);
  6016                  utils.fireCallback(instance, CALLBACK_TYPES.AGENT_DEBUG_EMAIL_NOTIF, emailNotifResp);
  6017                  break;
  6018              case MESSAGE_TYPES.MONITOR_CHAT:
  6019                  //TODO: do this
  6020                  break;
  6021              case MESSAGE_TYPES.LEAVE_CHAT:
  6022                  //TODO: do this
  6023                  break;
  6024          }
  6025      },
  6026      processDialerResponse: function(instance, response) {
  6027          var type = response.dialer_request['@type'];
  6028          var messageId = response.dialer_request['@message_id'];
  6029          var dest = messageId === "" ? "IS" : messageId.slice(0, 2);
  6030          var message = "Received " + type.toUpperCase() + " dialer response message from " + dest;
  6031          // log message response
  6032          utils.logMessage(LOG_LEVELS.INFO, message, response);
  6033          // Send generic on message response
  6034          utils.fireCallback(instance, CALLBACK_TYPES.ON_MESSAGE, response);
  6035          // Fire callback function
  6036          switch (type.toUpperCase()) {
  6037              case MESSAGE_TYPES.PREVIEW_DIAL_ID:
  6038                  var pdRequest = new PreviewDialRequest();
  6039                  var dialResponse = pdRequest.processResponse(response);
  6040                  if(dialResponse.action.toUpperCase() === "SEARCH"){
  6041                      utils.fireCallback(instance, CALLBACK_TYPES.LEAD_SEARCH, dialResponse);
  6042                  }else{
  6043                      utils.fireCallback(instance, CALLBACK_TYPES.PREVIEW_FETCH, dialResponse);
  6044                  }
  6045                  break;
  6046              case MESSAGE_TYPES.TCPA_SAFE_ID:
  6047                  var tcpaRequest = new TcpaSafeRequest();
  6048                  var tcpaResponse = tcpaRequest.processResponse(response);
  6049                  if(tcpaResponse.action.toUpperCase() === "SEARCH"){
  6050                      utils.fireCallback(instance, CALLBACK_TYPES.SAFE_MODE_SEARCH, tcpaResponse);
  6051                  }else{
  6052                      utils.fireCallback(instance, CALLBACK_TYPES.SAFE_MODE_FETCH, tcpaResponse);
  6053                  }
  6054                  break;
  6055          }
  6056      },
  6057      processRequest: function(instance, message) {
  6058          var type = message.ui_request['@type'];
  6059          // Fire callback function
  6060          switch (type.toUpperCase()) {
  6061              case MESSAGE_TYPES.CHAT_SEND:
  6062                  var chatSendRequest = new ChatSendRequest();
  6063                  var chatSendResponse = chatSendRequest.processResponse(message);
  6064                  utils.fireCallback(instance, CALLBACK_TYPES.CHAT, chatSendResponse);
  6065                  break;
  6066              case MESSAGE_TYPES.CHAT_ROOM_STATE:
  6067                  var chatRoomStateRequest = new ChatRoomStateRequest();
  6068                  var chatRoomStateResponse = chatRoomStateRequest.processResponse(message);
  6069                  utils.fireCallback(instance, CALLBACK_TYPES.CHAT_ROOM_STATE, chatRoomStateResponse);
  6070                  break;
  6071          }
  6072      },
  6073      processStats: function(instance, data) {
  6074          var type = data.ui_stats['@type'];
  6075          var message = "Received " + type.toUpperCase() + " response message from IS";
  6076          // Fire callback function
  6077          switch (type.toUpperCase()) {
  6078              case MESSAGE_TYPES.STATS_AGENT:
  6079                  var agentStats = UIModel.getInstance().agentStatsPacket.processResponse(data);
  6080                  utils.fireCallback(instance, CALLBACK_TYPES.STATS_AGENT, agentStats);
  6081                  break;
  6082              case MESSAGE_TYPES.STATS_AGENT_DAILY:
  6083                  var agentDailyStats = UIModel.getInstance().agentDailyStatsPacket.processResponse(data);
  6084                  utils.fireCallback(instance, CALLBACK_TYPES.STATS_AGENT_DAILY, agentDailyStats);
  6085                  // start daily stats interval timer, request update every second
  6086                  if(UIModel.getInstance().agentDailyIntervalId === null){
  6087                      UIModel.getInstance().agentDailyIntervalId = setInterval(utils.onAgentDailyStats, 1000);
  6088                  }
  6089                  break;
  6090              case MESSAGE_TYPES.STATS_CAMPAIGN:
  6091                  var campaignStats = UIModel.getInstance().campaignStatsPacket.processResponse(data);
  6092                  utils.fireCallback(instance, CALLBACK_TYPES.STATS_CAMPAIGN, campaignStats);
  6093                  break;
  6094              case MESSAGE_TYPES.STATS_QUEUE:
  6095                  var queueStats = UIModel.getInstance().queueStatsPacket.processResponse(data);
  6096                  utils.fireCallback(instance, CALLBACK_TYPES.STATS_QUEUE, queueStats);
  6097                  break;
  6098              case MESSAGE_TYPES.STATS_CHAT:
  6099                  var chatStats = UIModel.getInstance().chatQueueStatsPacket.processResponse(data);
  6100                  utils.fireCallback(instance, CALLBACK_TYPES.STATS_CHAT_QUEUE, chatStats);
  6101                  break;
  6102          }
  6103      },
  6104      /*
  6105       * Take the xml marked JSON, group and item property names and reformat to
  6106       * simple javascript object without the xml markers.
  6107       * Will work recursively down the tree on nested objects and arrays.
  6108       *
  6109       * example of acceptable response tree (groupProp = requeue_gates, itemProp = gate_group):
  6110       *   "requeue_gates": {
  6111       *       "gate_group": [
  6112       *           {
  6113       *               "@gate_group_id": "4",
  6114       *               "@group_name": "Test Gate Group",
  6115       *               "gates": {
  6116       *                   "gate": [
  6117       *                       {
  6118       *                           "@gate_desc": "",
  6119       *                           "@gate_id": "10951",
  6120       *                           "@gate_name": "CD ACD Queue"
  6121       *                       },
  6122       *                       {
  6123       *                           "@gate_desc": "",
  6124       *                           "@gate_id": "11036",
  6125       *                           "@gate_name": "Xerox Test Gate"
  6126       *                       }
  6127       *                   ]
  6128       *               },
  6129       *               "skills": {
  6130       *                   "skill": [
  6131       *                       {
  6132       *                           "@skill_desc": "",
  6133       *                           "@skill_id": "322",
  6134       *                           "@skill_name": "English"
  6135       *                       },
  6136       *                       {
  6137       *                           "@skill_desc": "",
  6138       *                           "@skill_id": "323",
  6139       *                           "@skill_name": "Spanish"
  6140       *                       }
  6141       *                   ]
  6142       *               }
  6143       *           },
  6144       *           {
  6145       *               "@gate_group_id": "14292",
  6146       *               "@group_name": "New Test Group",
  6147       *               "gates": {
  6148       *                   "gate": {
  6149       *                       "@gate_desc": "",
  6150       *                       "@gate_id": "15535",
  6151       *                       "@gate_name": "New Test Gate"
  6152       *                   }
  6153       *               },
  6154       *               "skills": {
  6155       *                   "skill": {
  6156       *                       "@skill_desc": "",
  6157       *                       "@skill_id": "1658",
  6158       *                       "@skill_name": "new skill"
  6159       *                   }
  6160       *               }
  6161       *           }
  6162       *       ]
  6163       *   }
  6164       *
  6165       *   OR
  6166       *
  6167       *   "outdial_dispositions": {
  6168       *       "@type": "GATE",
  6169       *       "disposition": [
  6170       *          {
  6171       *           "@contact_forwarding": "false",
  6172       *           "@disposition_id": "926",
  6173       *           "@is_complete": "1",
  6174       *           "@require_note": "0",
  6175       *           "@save_survey": "1",
  6176       *           "@xfer": "0",
  6177       *           "#text": "One B"
  6178       *          },
  6179       *          {
  6180       *           "@contact_forwarding": "false",
  6181       *           "@disposition_id": "926",
  6182       *           "@is_complete": "1",
  6183       *           "@require_note": "0",
  6184       *           "@save_survey": "1",
  6185       *           "@xfer": "0",
  6186       *           "#text": "One B"
  6187       *          }
  6188       *      ]
  6189       *   }
  6190       *
  6191       *   OR
  6192       *
  6193       *   "outdial_dispositions": {
  6194       *       "@type": "GATE",
  6195       *       "disposition": {
  6196       *          {
  6197       *           "@contact_forwarding": "false",
  6198       *           "@disposition_id": "926",
  6199       *           "@is_complete": "1",
  6200       *           "@require_note": "0",
  6201       *           "@save_survey": "1",
  6202       *           "@xfer": "0",
  6203       *           "#text": "One B"
  6204       *          }
  6205       *      }
  6206       *   }
  6207       */
  6208      processResponseCollection: function (response, groupProp, itemProp, textName) {
  6209          textName = textName || "text";
  6210          if (response[groupProp] && typeof response[groupProp][itemProp] !== 'undefined') {
  6211              var itemsRaw = response[groupProp][itemProp];
  6212              return this._processItems(itemsRaw, textName);
  6213          } else {
  6214              return [];
  6215          }
  6216      },
  6217      _processItems: function (itemsRaw, textName) {
  6218          var result = [];
  6219          if (typeof itemsRaw === "undefined" || itemsRaw === null) {
  6220              return result;
  6221          }
  6222          if (!Array.isArray(itemsRaw)) {
  6223              itemsRaw = [itemsRaw];
  6224          }
  6225          for (var i = 0; i < itemsRaw.length; i++) {
  6226              result.push(this._processItem(itemsRaw[i], textName));
  6227          }
  6228          return result;
  6229      },
  6230      _processItem: function (itemRaw, textName) {
  6231          /*
  6232           * Be sure that the item we are processing is not a #text node only, where the "texName" is also "text". If this
  6233           * is the case, it means there's a default value that needs to get converted and isn't going to be mapped to a custom
  6234           * field.  Therefore, we treat it as just a single value, not an object.
  6235           */
  6236          if (textName === "text" && Object.keys(itemRaw).length === 1 && itemRaw['#text'] != null) {
  6237              return this._tryConvertValueToBoolean(itemRaw["#text"]);
  6238          }
  6239          // Convert the raw item to a new item, with keys and values processed below
  6240          //
  6241          var item = {};
  6242          for (var key in itemRaw) {
  6243              var formattedKey = this._convertToFormattedKey(key, textName);
  6244              var value = itemRaw[key];
  6245              // If we aren't an object, set the value and continue to next key
  6246              if (typeof value !== "object") {
  6247                  item[formattedKey] = this._tryConvertValueToBoolean(value);
  6248                  continue;
  6249              }
  6250              if ((Array.isArray(value) && value.length === 0) || Object.keys(value).length === 0) {
  6251                  // Empty property
  6252                  item[formattedKey] = "";
  6253              } else if (Array.isArray(value) || Object.keys(value).length > 1) {
  6254                  // Array or object with more than one key
  6255                  formattedKey = this._convertKeyForCollection(formattedKey);
  6256                  item[formattedKey] = this._processItems(value, textName);
  6257              } else if (Object.keys(value).length === 1 && value['#text'] != null) {
  6258                  // One property of type "#text"
  6259                  item[formattedKey] = value['#text'];
  6260              } else {
  6261                  // One property not with key "#text"
  6262                  item[formattedKey] = this._processItems(value[Object.keys(value)[0]], "text");
  6263              }
  6264          }
  6265          return item;
  6266      },
  6267      _convertToFormattedKey: function (key, textName) {
  6268          var formattedKey;
  6269          if (key.match(/^#/)) {
  6270              // dealing with text property
  6271              formattedKey = textName;
  6272          } else {
  6273              // dealing with attribute
  6274              formattedKey = key.replace(/@/, ''); // remove leading '@'
  6275              formattedKey = formattedKey.replace(/_([a-z])/g, function (g) {
  6276                  return g[1].toUpperCase();
  6277              }); // convert to camelCase
  6278          }
  6279          return formattedKey;
  6280      },
  6281      _convertKeyForCollection: function (formattedKey) {
  6282          if (formattedKey.substr(formattedKey.length - 1) !== 's') {
  6283              return formattedKey + 's';
  6284          }
  6285          return formattedKey;
  6286      },
  6287      _tryConvertValueToBoolean: function (value) {
  6288          if (value === null) {
  6289              return null;
  6290          }
  6291          // can't convert 0 | 1 to boolean since some are counters
  6292          if (value.toUpperCase() === "TRUE") {
  6293              return true;
  6294          } else if (value.toUpperCase() === "FALSE") {
  6295              return false;
  6296          } else {
  6297              return value;
  6298          }
  6299      },
  6300      fireCallback: function(instance, type, response) {
  6301          response = response || "";
  6302          if (typeof type !== 'undefined' && typeof instance.callbacks[type] === 'function') {
  6303              instance.callbacks[type].call(instance, response);
  6304          }
  6305      },
  6306      setCallback: function(instance, type, callback) {
  6307          if (typeof type !== 'undefined' && typeof callback !== 'undefined') {
  6308              instance.callbacks[type] = callback;
  6309          }
  6310      },
  6311      getMessageId: function() {
  6312          function s4() {
  6313              return Math.floor((1 + Math.random()) * 0x10000)
  6314                  .toString(16)
  6315                  .substring(1);
  6316          }
  6317          return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
  6318              s4() + '-' + s4() + s4() + s4();
  6319      },
  6320      // check whether the given array of ids exist in the given array of objects
  6321      // if not available, remove the id
  6322      // returns the clean list of acceptable ids
  6323      checkExistingIds: function(objArray, idArray, idProperty) {
  6324          var availIds = [];
  6325          var removeIds = [];
  6326          // get list of available ids
  6327          for(var o = 0; o < objArray.length; o++){
  6328              availIds.push(parseInt(objArray[o][idProperty], 10));
  6329          }
  6330          // go through selected ids and mark unfound ones for removal
  6331          for(var i = 0; i < idArray.length; i++){
  6332              if(availIds.indexOf(parseInt(idArray[i],10)) === -1){
  6333                  // selected id not found in available list, mark for removal
  6334                  removeIds.push(parseInt(idArray[i],10));
  6335              }
  6336          }
  6337          // remove marked ids
  6338          for(var r = idArray.length -1; r >= 0; r--){
  6339              if(removeIds.indexOf(parseInt(idArray[r],10)) > -1){
  6340                  // remove
  6341                  idArray.splice(r,1);
  6342              }
  6343          }
  6344          return idArray;
  6345      },
  6346      // find an object by given id in an array of objects
  6347      findObjById: function(objArray, id, propName) {
  6348          for(var o = 0; o < objArray.length; o++){
  6349              var obj = objArray[o];
  6350              if(obj[propName] === id){
  6351                  return obj;
  6352              }
  6353          }
  6354          return null;
  6355      },
  6356      // check whether agent dialDest is either a 10-digit number or valid sip
  6357      validateDest: function(dialDest) {
  6358          var isValid = false;
  6359          var isNum = /^\d+$/.test(dialDest);
  6360          if(isNum && dialDest.length === 10){
  6361              // is a 10-digit number
  6362              isValid = true;
  6363          }else if(dialDest.slice(0,4).toLowerCase() === "sip:" && dialDest.indexOf("@") !== -1){
  6364              // has sip prefix and '@'
  6365              isValid = true;
  6366          }
  6367          return isValid;
  6368      },
  6369      // pass in MESSAGE_TYPE string (e.g. "CANCEL-CALLBACK"),
  6370      // return corresponding CALLBACK_TYPE function name string (e.g. "callbackCancelResponse")
  6371      findCallbackBasedOnMessageType: function(messageType) {
  6372          var callbackFnName = "";
  6373          for(var key in MESSAGE_TYPES){
  6374              if(MESSAGE_TYPES[key] === messageType){
  6375                  callbackFnName = CALLBACK_TYPES[key];
  6376              }
  6377          }
  6378          return callbackFnName;
  6379      },
  6380      // add message, detail, and status values to the formattedResponse
  6381      // returned from each request processResponse method
  6382      buildDefaultResponse: function(response) {
  6383          var message = "";
  6384          var detail = "";
  6385          var status = "";
  6386          var msg = "";
  6387          var det = "";
  6388          var stat = "";
  6389          // add message and detail if present
  6390          if(response.ui_response){
  6391              msg = response.ui_response.message;
  6392              det = response.ui_response.detail;
  6393              stat = response.ui_response.status;
  6394          }else if(response.ui_notification){
  6395              msg = response.ui_notification.message;
  6396              det = response.ui_notification.detail;
  6397              stat = response.ui_notification.status;
  6398          }
  6399          if(msg){
  6400              message = msg['#text'] || "";
  6401          }
  6402          if(det){
  6403              detail = det['#text'] || "";
  6404          }
  6405          if(stat){
  6406              status = stat['#text'] || "";
  6407          }
  6408          return ({
  6409              message: message,
  6410              detail: detail,
  6411              status: status
  6412          });
  6413      },
  6414      toString: function(val) {
  6415          if(val){
  6416              return val.toString();
  6417          }else{
  6418              return "";
  6419          }
  6420      },
  6421      // safely check if property exists and return empty string
  6422      // instead of undefined if it doesn't exist
  6423      // convert "TRUE" | "FALSE" to boolean
  6424      getText: function(obj,prop) {
  6425          var o = obj[prop];
  6426          if(o && o['#text']){
  6427              if(o['#text'].toUpperCase() === "TRUE"){
  6428                  return true;
  6429              }else if(o['#text'].toUpperCase() === "FALSE"){
  6430                  return false;
  6431              }else{
  6432                  return o['#text'] || "";
  6433              }
  6434          }else{
  6435              return "";
  6436          }
  6437      },
  6438      // safely check if property exists and return empty string
  6439      // instead of undefined if it doesn't exist
  6440      // convert "TRUE" | "FALSE" to boolean
  6441      getAttribute: function(obj,prop) {
  6442          var o = obj[prop];
  6443          if(o && o[prop]){
  6444              if(o[prop].toUpperCase() === "TRUE"){
  6445                  return true;
  6446              }else if(o[prop].toUpperCase() === "FALSE"){
  6447                  return false;
  6448              }else{
  6449                  return o[prop] || "";
  6450              }
  6451          }else{
  6452              return "";
  6453          }
  6454      },
  6455      // Parses a string of key value pairs and returns an Array of KeyValue objects.
  6456      // @param str The string of keyvalue pairs to parse
  6457      // @param outerDelimiter The delimiter that separates each keyValue pair
  6458      // @param innerDelimiter The delimiter that separates each key from its value
  6459      parseKeyValuePairsFromString: function(str, outerDelimiter, innerDelimiter) {
  6460          if (!str){
  6461              return [];
  6462          }
  6463          var arr = str.split(outerDelimiter).reduce(function(dict, pair){
  6464              var keyValue = pair.split(innerDelimiter);
  6465              dict[keyValue[0]] = keyValue[1];
  6466              return dict;
  6467          },{});
  6468          return arr;
  6469      },
  6470      // Finds a request by responseTo id
  6471      findRequestById: function(instance, id) {
  6472          var request = null;
  6473          for(var i = 0; i < instance._requests.length; i++){
  6474              if(instance._requests[i].id === id){
  6475                  request = instance._requests[i];
  6476                  break;
  6477              }
  6478          }
  6479          return request;
  6480      },
  6481      // called every 30 seconds letting intelliQueue know
  6482      // not to archive the call so dispositions and other call
  6483      // clean up actions can happen
  6484      sendPingCallMessage: function() {
  6485          UIModel.getInstance().pingCallRequest = new PingCallRequest();
  6486          var msg = UIModel.getInstance().pingCallRequest.formatJSON();
  6487          var msgObj = JSON.parse(msg);
  6488          var agentId = utils.getText(msgObj.ui_request,'agent_id');
  6489          var uii = utils.getText(msgObj.ui_request,'uii');
  6490          if(agentId === "" || uii === ""){
  6491              utils.logMessage(LOG_LEVELS.WARN, "PING-CALL message failed, agentId or UII is empty", msgObj);
  6492          }else{
  6493              utils.sendMessage(UIModel.getInstance().libraryInstance, msg);
  6494          }
  6495      },
  6496      // called every 5 seconds to request stats from IntelliServices
  6497      sendStatsRequestMessage: function() {
  6498          UIModel.getInstance().statsRequest = new StatsRequest();
  6499          var msg = UIModel.getInstance().statsRequest.formatJSON();
  6500          utils.sendMessage(UIModel.getInstance().libraryInstance, msg);
  6501      },
  6502      // called every second
  6503      // if we have received agent daily stats
  6504      // start incrementing various data points since not all
  6505      // data is incremented when we want on the IntelliServices side
  6506      onAgentDailyStats: function() {
  6507          if(Object.keys(UIModel.getInstance().agentDailyStats).length !== 0){
  6508              var agentSettings = UIModel.getInstance().agentSettings,
  6509                  stats = UIModel.getInstance().agentDailyStats;
  6510              var curLoginTime = stats.totalLoginTime;
  6511              stats.totalLoginTime = Number(curLoginTime) + 1;
  6512              if(agentSettings.isOffhook){
  6513                  var curOffhookTime = stats.totalOffhookTime;
  6514                  stats.totalOffhookTime = Number(curOffhookTime) + 1;
  6515              }
  6516              if(agentSettings.currentState == 'ENGAGED'){
  6517                  var curTalkTime = stats.totalTalkTime;
  6518                  stats.totalTalkTime = Number(curTalkTime) + 1;
  6519                  var curCallTime = stats.currCallTime;
  6520                  stats.currCallTime = Number(curCallTime) + 1;
  6521              }
  6522          }
  6523      }
  6524  };
  6525  // CONSTANTS
  6526  /*jshint esnext: true */
  6527  const LOG_LEVELS ={
  6528      "DEBUG":"debug",
  6529      "STATS":"stats",
  6530      "INFO":"info",
  6531      "WARN":"warn",
  6532      "ERROR":"error"
  6533  };
  6534  // add all callback types to setCallback method description
  6535  const CALLBACK_TYPES = {
  6536      "ADD_SESSION":"addSessionNotification",
  6537      "AGENT_STATE":"agentStateResponse",
  6538      "ACK":"acknowledgeResponse",
  6539      "BARGE_IN":"bargeInResponse",
  6540      "CLOSE_SOCKET":"closeResponse",
  6541      "COACH_CALL":"coachResponse",
  6542      "CONFIG":"configureResponse",
  6543      "CALL_NOTES":"callNotesResponse",
  6544      "CALLBACK_PENDING":"callbacksPendingResponse",
  6545      "CALLBACK_CANCEL":"callbackCancelResponse",
  6546      "CAMPAIGN_DISPOSITIONS":"campaignDispositionsResponse",
  6547      "CHAT":"chatResponse",                          // internal chat
  6548      "CHAT_ACTIVE":"chatActiveNotification",         // external chat
  6549      "CHAT_CANCELLED":"chatCancelledNotification",   // external chat
  6550      "CHAT_INACTIVE":"chatInactiveNotification",     // external chat
  6551      "CHAT_PRESENTED":"chatPresentedNotification",   // external chat
  6552      "CHAT_TYPING":"chatTypingNotification",         // external chat
  6553      "CHAT_MESSAGE":"chatMessageNotification",       // external chat
  6554      "CHAT_NEW":"chatNewNotification",               // external chat
  6555      "CHAT_LIST":"chatListResponse",                 // external chat
  6556      "CHAT_ADD_SESSION":"addChatSessionNotification",// external chat
  6557      "CHAT_STOP_MONITOR":"stopAgentChatMonitorNotification",// external chat
  6558      "CHAT_CLIENT_RECONNECT" : "chatClientReconnectNotification",
  6559      "CHAT_STATE":"chatStateResponse",               // external chat
  6560      "CHAT_ROOM_STATE":"chatRoomStateResponse",
  6561      "DIAL_GROUP_CHANGE":"dialGroupChangeNotification",
  6562      "DIAL_GROUP_CHANGE_PENDING":"dialGroupChangePendingNotification",
  6563      "DROP_SESSION":"dropSessionNotification",
  6564      "EARLY_UII":"earlyUiiNotification",
  6565      "END_CALL":"endCallNotification",
  6566      "GATES_CHANGE":"gatesChangeNotification",
  6567      "GENERIC_NOTIFICATION":"genericNotification",
  6568      "GENERIC_RESPONSE":"genericResponse",
  6569      "HOLD":"holdResponse",
  6570      "LOG_RESULTS":"logResultsResponse",
  6571      "LOG_CONSOLE_RESULTS":"logConsoleResultsResponse",
  6572      "LOGIN":"loginResponse",
  6573      "LOGOUT":"logoutResponse",
  6574      "NEW_CALL":"newCallNotification",
  6575      "LEAD_HISTORY":"leadHistoryResponse",
  6576      "LEAD_INSERT":"leadInsertResponse",
  6577      "LEAD_SEARCH":"leadSearchResponse",
  6578      "LEAD_UPDATE":"leadUpdateResponse",
  6579      "OFFHOOK_INIT":"offhookInitResponse",
  6580      "OFFHOOK_TERM":"offhookTermNotification",
  6581      "OPEN_SOCKET":"openResponse",
  6582      "PAUSE_RECORD":"pauseRecordResponse",
  6583      "PENDING_DISP":"pendingDispNotification",
  6584      "PENDING_CHAT_DISP":"pendingChatDispNotification",
  6585      "PREVIEW_FETCH":"previewFetchResponse",
  6586      "PREVIEW_LEAD_STATE":"previewLeadStateNotification",
  6587      "RECORD":"recordResponse",
  6588      "REQUEUE":"requeueResponse",
  6589      "REVERSE_MATCH":"reverseMatchNotification",
  6590      "SAFE_MODE_FETCH":"safeModeFetchResponse",
  6591      "SAFE_MODE_SEARCH":"safeModeSearchResponse",
  6592      "SCRIPT_CONFIG":"scriptConfigResponse",
  6593      "SILENT_MONITOR":"monitorResponse",
  6594      "STATS_AGENT":"agentStats",
  6595      "STATS_AGENT_DAILY":"agentDailyStats",
  6596      "STATS_CAMPAIGN":"campaignStats",
  6597      "STATS_QUEUE":"queueStats",
  6598      "STATS_CHAT_QUEUE":"chatQueueStats",
  6599      "SUPERVISOR_LIST":"supervisorListResponse",
  6600      "TCPA_SAFE_LEAD_STATE":"tcpaSafeLeadStateNotification",
  6601      "XFER_COLD":"coldXferResponse",
  6602      "XFER_WARM":"warmXferResponse",
  6603      "DIRECT_AGENT_TRANSFER_LIST": "directAgentTransferListResponse",
  6604      "DIRECT_AGENT_TRANSFER": "directAgentTransferResponse",
  6605      "DIRECT_AGENT_TRANSFER_NOTIF": "directAgentTransferNotification",
  6606      "AGENT_DEBUG_EMAIL_NOTIF": "agentDebugEmailNotification"
  6607  };
  6608  const MESSAGE_TYPES = {
  6609      "ACK":"ACK",
  6610      "ADD_SESSION":"ADD-SESSION",
  6611      "AGENT_DEBUG_EMAIL": "AGENT-DEBUG-EMAIL",
  6612      "BARGE_IN":"BARGE-IN",
  6613      "AGENT_STATE":"AGENT-STATE",
  6614      "CALL_NOTES":"CALL-NOTES",
  6615      "CALLBACK_PENDING":"PENDING-CALLBACKS",
  6616      "CALLBACK_CANCEL":"CANCEL-CALLBACK",
  6617      "CAMPAIGN_DISPOSITIONS":"CAMPAIGN-DISPOSITIONS",
  6618      "CHAT_SEND":"CHAT",                                     // internal chat
  6619      "CHAT_ALIAS":"CHAT-ALIAS",                              // internal chat
  6620      "CHAT_ROOM":"CHAT-ROOM",                                // internal chat
  6621      "CHAT_ROOM_STATE":"CHAT-ROOM-STATE",                    // internal chat
  6622      "CHAT_ACTIVE":"CHAT-ACTIVE",                            // external chat
  6623      "CHAT_CANCELLED":"CHAT-CANCELLED",                      // external chat
  6624      "CHAT_INACTIVE":"CHAT-INACTIVE",                        // external chat
  6625      "CHAT_DISPOSITION":"CHAT-DISPOSITION",                  // external chat
  6626      "CHAT_MESSAGE":"CHAT-MESSAGE",                          // external chat
  6627      "CHAT_NEW":"NEW-CHAT",                                  // external chat
  6628      "CHAT_PRESENTED":"CHAT-PRESENTED",                      // external chat
  6629      "CHAT_PRESENTED_RESPONSE":"CHAT-PRESENTED-RESPONSE",    // external chat
  6630      "CHAT_REQUEUE":"CHAT-REQUEUE",                          // external chat
  6631      "CHAT_STATE":"CHAT-STATE",                              // external chat
  6632      "CHAT_TYPING":"CHAT-TYPING",                            // external chat
  6633      "MONITOR_CHAT":"CHAT-MONITOR",                          // external chat
  6634      "CHAT_ADD_SESSION":"ADD-CHAT-SESSION",                  // external chat
  6635      "STOP_MONITOR_CHAT":"CHAT-DROP-MONITORING-SESSION",     // external chat
  6636      "LEAVE_CHAT":"CHAT-DROP-SESSION",                       // external chat
  6637      "CHAT_LIST":"CHAT-LIST",                                // external chat
  6638      "CHAT_AGENT_END" : "CHAT-END",                          // external chat
  6639      "CHAT_CLIENT_RECONNECT" : "CHAT-CLIENT-RECONNECT",      // external chat
  6640      "CHAT_MANUAL_SMS": "MANUAL-SMS",                        // external chat
  6641      "PENDING_CHAT_DISP": "PENDING-CHAT-DISP",               // external chat
  6642      "DIAL_GROUP_CHANGE":"DIAL_GROUP_CHANGE",
  6643      "DIAL_GROUP_CHANGE_PENDING":"DIAL_GROUP_CHANGE_PENDING",
  6644      "DROP_SESSION":"DROP-SESSION",
  6645      "EARLY_UII":"EARLY_UII",
  6646      "END_CALL":"END-CALL",
  6647      "GATES_CHANGE":"GATES_CHANGE",
  6648      "GENERIC":"GENERIC",
  6649      "HANGUP":"HANGUP",
  6650      "HOLD":"HOLD",
  6651      "INBOUND_DISPOSITION":"INBOUND-DISPOSITION",
  6652      "LEAD_HISTORY":"LEAD-HISTORY",
  6653      "LEAD_INSERT":"LEAD-INSERT",
  6654      "LEAD_UPDATE":"LEAD-UPDATE",
  6655      "LOGIN":"LOGIN",
  6656      "LOGOUT":"LOGOUT",
  6657      "NEW_CALL":"NEW-CALL",
  6658      "OFFHOOK_INIT":"OFF-HOOK-INIT",
  6659      "OFFHOOK_TERM":"OFF-HOOK-TERM",
  6660      "ON_MESSAGE":"ON-MESSAGE",
  6661      "ONE_TO_ONE_OUTDIAL":"ONE-TO-ONE-OUTDIAL",
  6662      "ONE_TO_ONE_OUTDIAL_CANCEL":"ONE-TO-ONE-OUTDIAL-CANCEL",
  6663      "OUTDIAL_DISPOSITION":"OUTDIAL-DISPOSITION",
  6664      "PAUSE_RECORD":"PAUSE-RECORD",
  6665      "PING_CALL":"PING-CALL",
  6666      "PREVIEW_DIAL":"PREVIEW-DIAL",
  6667      "PENDING_DISP":"PENDING_DISP",
  6668      "PREVIEW_DIAL_ID":"PREVIEW_DIAL",
  6669      "PREVIEW_LEAD_STATE":"PREVIEW-LEAD-STATE",
  6670      "RECORD":"RECORD",
  6671      "REQUEUE":"RE-QUEUE",
  6672      "REVERSE_MATCH":"REVERSE_MATCH",
  6673      "SCRIPT_CONFIG":"SCRIPT-CONFIG",
  6674      "SCRIPT_RESULT":"SCRIPT-RESULT",
  6675      "STATS":"STATS",
  6676      "STATS_AGENT":"AGENT",
  6677      "STATS_AGENT_DAILY":"AGENTDAILY",
  6678      "STATS_CAMPAIGN":"CAMPAIGN",
  6679      "STATS_QUEUE":"GATE",
  6680      "STATS_CHAT":"CHAT",
  6681      "SUPERVISOR_LIST":"SUPERVISOR-LIST",                // internal chat
  6682      "TCPA_SAFE":"TCPA-SAFE",
  6683      "TCPA_SAFE_ID":"TCPA_SAFE",
  6684      "TCPA_SAFE_LEAD_STATE":"TCPA-SAFE-LEAD-STATE",
  6685      "XFER_COLD":"COLD-XFER",
  6686      "XFER_WARM":"WARM-XFER",
  6687      "XFER_WARM_CANCEL":"WARM-XFER-CANCEL",
  6688      "DIRECT_AGENT_TRANSFER_LIST": "DIRECT-AGENT-TRANSFER-LIST",
  6689      "DIRECT_AGENT_TRANSFER": "DIRECT-AGENT-TRANSFER",
  6690      "DIRECT_AGENT_ROUTE": "DIRECT-AGENT-ROUTE",
  6691      "UPDATE_DIAL_DESTINATION": "UPDATE_DIAL_DESTINATION"
  6692  };
  6693  /*
  6694   * Init wrapper for the core module.
  6695   * @param {Object} The Object that the library gets attached to in
  6696   * library.init.js.  If the library was not loaded with an AMD loader such as
  6697   * require.js, this is the global Object.
  6698   */
  6699  function initAgentLibraryCore (context) {
  6700      'use strict';
  6701      /**
  6702       * This is the constructor for the Library Object. Note that the constructor is also being
  6703       * attached to the context that the library was loaded in.
  6704       * @param {Object} [config={}] Set socket url and callback functions.
  6705       * @constructor
  6706       * @namespace Core
  6707       * @memberof AgentLibrary
  6708       * @property {object} callbacks Internal map of registered callback functions
  6709       * @property {array} _requests Internal map of requests by message id, private property.
  6710       * @property {array} _queuedMsgs Array of pending messages to be sent when socket reconnected
  6711       * @property {boolean} _isReconnect Whether or not we are doing a reconnect for the socket
  6712       * @example
  6713       * var Lib = new AgentLibrary({
  6714       *      socketDest:'ws://d01-test.cf.dev:8080',
  6715       *      callbacks: {
  6716       *          closeResponse: onCloseFunction,
  6717       *          openResponse: onOpenFunction
  6718       *      }
  6719       * });
  6720       */
  6721      var AgentLibrary = context.AgentLibrary = function (config) {
  6722          config = config || {};
  6723          // define properties
  6724          this.callbacks = {};
  6725          this._requests = [];
  6726          this._queuedMsgs = [];
  6727          this._isReconnect = false;
  6728          // start with new model instance
  6729          UIModel.resetInstance();
  6730          // set instance on model object
  6731          UIModel.getInstance().libraryInstance = this;
  6732          // initialize indexedDB for logging
  6733          this.openLogger();
  6734          this.openConsoleLogger();
  6735          // set default values
  6736          if(typeof config.callbacks !== 'undefined'){
  6737              this.callbacks = config.callbacks;
  6738          }
  6739          if(typeof config.socketDest !== 'undefined'){
  6740              UIModel.getInstance().applicationSettings.socketDest = config.socketDest;
  6741              this.openSocket();
  6742          }else{
  6743              // todo default socket address?
  6744          }
  6745          return this;
  6746      };
  6747      /**
  6748       * Set multiple callback functions based on type
  6749       * @memberof AgentLibrary.Core
  6750       * @param {Object} callbackMap Contains map of callback types to their respective functions:<br />
  6751       * <tt>callbackMap = {<br />
  6752       *      closeResponse: onCloseFunction,<br />
  6753       *      openResponse: onOpenFunction<br />
  6754       * }
  6755       * </tt>
  6756       *<br />
  6757       * Possible callback types:
  6758       * <li>"addSessionNotification"</li>
  6759       * <li>"agentStateResponse"</li>
  6760       * <li>"acknowledgeResponse"</li>
  6761       * <li>"bargeInResponse"</li>
  6762       * <li>"closeResponse"</li>
  6763       * <li>"coachResponse"</li>
  6764       * <li>"configureResponse"</li>
  6765       * <li>"callNotesResponse"</li>
  6766       * <li>"callbacksPendingResponse"</li>
  6767       * <li>"callbackCancelResponse"</li>
  6768       * <li>"campaignDispositionsResponse"</li>
  6769       * <li>"chatResponse"</li>
  6770       * <li>"dialGroupChangeNotification"</li>
  6771       * <li>"dialGroupChangePendingNotification"</li>
  6772       * <li>"dropSessionNotification"</li>
  6773       * <li>"earlyUiiNotification"</li>
  6774       * <li>"endCallNotification"</li>
  6775       * <li>"gatesChangeNotification"</li>
  6776       * <li>"genericNotification"</li>
  6777       * <li>"genericResponse"</li>
  6778       * <li>"holdResponse"</li>
  6779       * <li>"leadSearchResponse"</li>
  6780       * <li>"loginResponse"</li>
  6781       * <li>"logoutResponse"</li>
  6782       * <li>"monitorResponse"</li>
  6783       * <li>"newCallNotification"</li>
  6784       * <li>"offhookInitResponse"</li>
  6785       * <li>"offhookTermNotification"</li>
  6786       * <li>"openResponse"</li>
  6787       * <li>"pauseRecordResponse"</li>
  6788       * <li>"pendingDispNotification"</li>
  6789       * <li>"previewFetchResponse"</li>
  6790       * <li>"previewLeadStateNotification"</li>
  6791       * <li>"recordResponse"</li>
  6792       * <li>"requeueResponse"</li>
  6793       * <li>"reverseMatchNotification"</li>
  6794       * <li>"safeModeFetchResponse"</li>
  6795       * <li>"safeModeSearchResponse"</li>
  6796       * <li>"scriptConfigResponse"</li>
  6797       * <li>"supervisorListResponse"</li>
  6798       * <li>"coldXferResponse"</li>
  6799       * <li>"warmXferResponse"</li>
  6800       * <li>"agentStats"</li>
  6801       * <li>"agentDailyStats"</li>
  6802       * <li>"campaignStats"</li>
  6803       * <li>"queueStats"</li>
  6804       * <li>"chatQueueStats"</li>
  6805       * @type {object}
  6806       */
  6807      AgentLibrary.prototype.setCallbacks = function(callbackMap) {
  6808          for(var property in callbackMap) {
  6809              this.callbacks[property] = callbackMap[property];
  6810          }
  6811      };
  6812      /**
  6813       * Set an individual callback function for the given type
  6814       * @memberof AgentLibrary.Core
  6815       * @param {string} type The name of the event that fires the callback function
  6816       * @param {function} callback The function to call for the given type
  6817       */
  6818      AgentLibrary.prototype.setCallback = function(type, callback) {
  6819          this.callbacks[type] = callback;
  6820      };
  6821      /**
  6822       * Get the map of all registered callbacks
  6823       * @memberof AgentLibrary.Core
  6824       * @returns {array}
  6825       */
  6826      AgentLibrary.prototype.getCallbacks = function(){
  6827          return this.callbacks;
  6828      };
  6829      /**
  6830       * Get a given registered callback by type
  6831       * @memberof AgentLibrary.Core
  6832       * @returns {object}
  6833       */
  6834      AgentLibrary.prototype.getCallback = function(type){
  6835          return this.callbacks[type];
  6836      };
  6837      /**
  6838       * Get the socket connection to IntelliSocket
  6839       * @memberof AgentLibrary.Core
  6840       * @returns {object}
  6841       */
  6842      AgentLibrary.prototype.getSocket = function(type){
  6843          return this.socket;
  6844      };
  6845      /**
  6846       * @namespace Requests
  6847       * @memberof AgentLibrary.Core
  6848       */
  6849      ////////////////////////////
  6850      // requests and responses //
  6851      ////////////////////////////
  6852      /**
  6853       * Get outgoing Login Request object
  6854       * @memberof AgentLibrary.Core.Requests
  6855       * @returns {object}
  6856       */
  6857      AgentLibrary.prototype.getLoginRequest = function() {
  6858          return UIModel.getInstance().loginRequest;
  6859      };
  6860      /**
  6861       * Get outgoing Config Request object
  6862       * @memberof AgentLibrary.Core.Requests
  6863       * @returns {object}
  6864       */
  6865      AgentLibrary.prototype.getConfigRequest = function() {
  6866          return UIModel.getInstance().configRequest;
  6867      };
  6868      /**
  6869       * Get outgoing Logout Request object
  6870       * @memberof AgentLibrary.Core.Requests
  6871       * @returns {object}
  6872       */
  6873      AgentLibrary.prototype.getLogoutRequest = function() {
  6874          return UIModel.getInstance().logoutRequest;
  6875      };
  6876      /**
  6877       * Get latest Agent Daily Stats object
  6878       * @memberof AgentLibrary.Core.Requests
  6879       * @returns {object}
  6880       */
  6881      AgentLibrary.prototype.getAgentDailyStats = function() {
  6882          return UIModel.getInstance().agentDailyStats;
  6883      };
  6884      /**
  6885       * Get latest Call Tokens object
  6886       * @memberof AgentLibrary.Core.Requests
  6887       * @returns {object}
  6888       */
  6889      AgentLibrary.prototype.getCallTokens = function() {
  6890          return UIModel.getInstance().callTokens;
  6891      };
  6892      /**
  6893       * Get latest outgoing Agent State Request object
  6894       * @memberof AgentLibrary.Core.Requests
  6895       * @returns {object}
  6896       */
  6897      AgentLibrary.prototype.getAgentStateRequest = function() {
  6898          return UIModel.getInstance().agentStateRequest;
  6899      };
  6900      /**
  6901       * Get latest outgoing offhook init Request object
  6902       * @memberof AgentLibrary.Core.Requests
  6903       * @returns {object}
  6904       */
  6905      AgentLibrary.prototype.getOffhookInitRequest = function() {
  6906          return UIModel.getInstance().offhookInitRequest;
  6907      };
  6908      /**
  6909       * Get latest outgoing offhook termination Request object
  6910       * @memberof AgentLibrary.Core.Requests
  6911       * @returns {object}
  6912       */
  6913      AgentLibrary.prototype.getOffhookTermRequest = function() {
  6914          return UIModel.getInstance().offhookTermRequest;
  6915      };
  6916      /**
  6917       * Get latest outgoing Hangup Request object
  6918       * @memberof AgentLibrary.Core.Requests
  6919       * @returns {object}
  6920       */
  6921      AgentLibrary.prototype.getHangupRequest = function() {
  6922          return UIModel.getInstance().hangupRequest;
  6923      };
  6924      /**
  6925       * Get latest outgoing Preview Dial Request object
  6926       * @memberof AgentLibrary.Core.Requests
  6927       * @returns {object}
  6928       */
  6929      AgentLibrary.prototype.getPreviewDialRequest = function() {
  6930          return UIModel.getInstance().previewDialRequest;
  6931      };
  6932      /**
  6933       * Get latest TCPA Safe Request object
  6934       * @memberof AgentLibrary.Core.Requests
  6935       * @returns {object}
  6936       */
  6937      AgentLibrary.prototype.getTcpaSafeRequest = function() {
  6938          return UIModel.getInstance().tcpaSafeRequest;
  6939      };
  6940      /**
  6941       * Get latest Manual Outdial Request object
  6942       * @memberof AgentLibrary.Core.Requests
  6943       * @returns {object}
  6944       */
  6945      AgentLibrary.prototype.getManualOutdialRequest = function() {
  6946          return UIModel.getInstance().oneToOneOutdialRequest;
  6947      };
  6948      /**
  6949       * Get latest Manual Outdial Cancel Request object
  6950       * @memberof AgentLibrary.Core.Requests
  6951       * @returns {object}
  6952       */
  6953      AgentLibrary.prototype.getManualOutdialCancelRequest = function() {
  6954          return UIModel.getInstance().oneToOneOutdialCancelRequest;
  6955      };
  6956      /**
  6957       * Get latest Call Notes Request object
  6958       * @memberof AgentLibrary.Core.Requests
  6959       * @returns {object}
  6960       */
  6961      AgentLibrary.prototype.getCallNotesRequest = function() {
  6962          return UIModel.getInstance().callNotesRequest;
  6963      };
  6964      /**
  6965       * Get latest Campaign Dispositions Request object
  6966       * @memberof AgentLibrary.Core.Requests
  6967       * @returns {object}
  6968       */
  6969      AgentLibrary.prototype.getCampaignDispositionsRequest = function() {
  6970          return UIModel.getInstance().campaignDispositionsRequest;
  6971      };
  6972      /**
  6973       * Get latest Disposition Call Request object
  6974       * @memberof AgentLibrary.Core.Requests
  6975       * @returns {object}
  6976       */
  6977      AgentLibrary.prototype.getDispositionRequest = function() {
  6978          return UIModel.getInstance().dispositionRequest;
  6979      };
  6980      /**
  6981       * Get latest Disposition Manual Pass Request object
  6982       * @memberof AgentLibrary.Core.Requests
  6983       * @returns {object}
  6984       */
  6985      AgentLibrary.prototype.getDispositionManualPassRequest = function() {
  6986          return UIModel.getInstance().dispositionManualPassRequest;
  6987      };
  6988      /**
  6989       * Get latest Warm Transfer Request object
  6990       * @memberof AgentLibrary.Core.Requests
  6991       * @returns {object}
  6992       */
  6993      AgentLibrary.prototype.getWarmTransferRequest = function() {
  6994          return UIModel.getInstance().warmXferRequest;
  6995      };
  6996      /**
  6997       * Get latest Cold Transfer Request object
  6998       * @memberof AgentLibrary.Core.Requests
  6999       * @returns {object}
  7000       */
  7001      AgentLibrary.prototype.getColdTransferRequest = function() {
  7002          return UIModel.getInstance().coldXferRequest;
  7003      };
  7004      /**
  7005       * Get latest Warm Transfer Cancel Request object
  7006       * @memberof AgentLibrary.Core.Requests
  7007       * @returns {object}
  7008       */
  7009      AgentLibrary.prototype.getWarmTransferCancelRequest = function() {
  7010          return UIModel.getInstance().warmXferCancelRequest;
  7011      };
  7012      /**
  7013       * Get latest Requeue Request object
  7014       * @memberof AgentLibrary.Core.Requests
  7015       * @returns {object}
  7016       */
  7017      AgentLibrary.prototype.getRequeueRequest = function() {
  7018          return UIModel.getInstance().requeueRequest;
  7019      };
  7020      /**
  7021       * Get latest Barge-In Request object
  7022       * @memberof AgentLibrary.Core.Requests
  7023       * @returns {object}
  7024       */
  7025      AgentLibrary.prototype.getBargeInRequest = function() {
  7026          return UIModel.getInstance().bargeInRequest;
  7027      };
  7028      /**
  7029       * Get latest Hold Request object
  7030       * @memberof AgentLibrary.Core.Requests
  7031       * @returns {object}
  7032       */
  7033      AgentLibrary.prototype.getHoldRequest = function() {
  7034          return UIModel.getInstance().holdRequest;
  7035      };
  7036      /**
  7037       * Get latest Pause Record Request object
  7038       * @memberof AgentLibrary.Core.Requests
  7039       * @returns {object}
  7040       */
  7041      AgentLibrary.prototype.getPauseRecordRequest = function() {
  7042          return UIModel.getInstance().pauseRecordRequest;
  7043      };
  7044      /**
  7045       * Get latest Record Request object
  7046       * @memberof AgentLibrary.Core.Requests
  7047       * @returns {object}
  7048       */
  7049      AgentLibrary.prototype.getRecordRequest = function() {
  7050          return UIModel.getInstance().recordRequest;
  7051      };
  7052      /**
  7053       * Get latest Chat Presented Request object
  7054       * @memberof AgentLibrary.Core.Requests
  7055       * @returns {object}
  7056       */
  7057      AgentLibrary.prototype.getChatPresentedRequest = function() {
  7058          return UIModel.getInstance().chatPresentedRequest;
  7059      };
  7060      /**
  7061       * Get latest Chat Disposition Request object
  7062       * @memberof AgentLibrary.Core.Requests
  7063       * @returns {object}
  7064       */
  7065      AgentLibrary.prototype.getChatDispositionRequest = function() {
  7066          return UIModel.getInstance().chatDispositionRequest;
  7067      };
  7068      /**
  7069       * Get latest Chat Message Request object
  7070       * @memberof AgentLibrary.Core.Requests
  7071       * @returns {object}
  7072       */
  7073      AgentLibrary.prototype.getChatMessageRequest = function() {
  7074          return UIModel.getInstance().chatMessageRequest;
  7075      };
  7076      /**
  7077       * Get latest Chat Requeue Request object
  7078       * @memberof AgentLibrary.Core.Requests
  7079       * @returns {object}
  7080       */
  7081      AgentLibrary.prototype.getChatRequeueRequest = function() {
  7082          return UIModel.getInstance().chatRequeueRequest;
  7083      };
  7084      /**
  7085       * Get latest Chat Typing Request object
  7086       * @memberof AgentLibrary.Core.Requests
  7087       * @returns {object}
  7088       */
  7089      AgentLibrary.prototype.getChatTypingRequest = function() {
  7090          return UIModel.getInstance().chatTypingRequest;
  7091      };
  7092      /**
  7093       * Get latest Agent Stats object
  7094       * @memberof AgentLibrary.Core.Requests
  7095       * @returns {object}
  7096       */
  7097      AgentLibrary.prototype.getAgentStatsPacket = function() {
  7098          return UIModel.getInstance().agentStatsPacket;
  7099      };
  7100      /**
  7101       * Get latest Agent Daily Stats object
  7102       * @memberof AgentLibrary.Core.Requests
  7103       * @returns {object}
  7104       */
  7105      AgentLibrary.prototype.getAgentDailyStatsPacket = function() {
  7106          return UIModel.getInstance().agentDailyStatsPacket;
  7107      };
  7108      /**
  7109       * Get latest Queue Stats object
  7110       * @memberof AgentLibrary.Core.Requests
  7111       * @returns {object}
  7112       */
  7113      AgentLibrary.prototype.getQueueStatsPacket = function() {
  7114          return UIModel.getInstance().queueStatsPacket;
  7115      };
  7116      /**
  7117       * Get latest Chat Queue Stats object
  7118       * @memberof AgentLibrary.Core.Requests
  7119       * @returns {object}
  7120       */
  7121      AgentLibrary.prototype.getChatQueueStatsPacket = function() {
  7122          return UIModel.getInstance().chatQueueStatsPacket;
  7123      };
  7124      /**
  7125       * Get latest Campaign Stats object
  7126       * @memberof AgentLibrary.Core.Requests
  7127       * @returns {object}
  7128       */
  7129      AgentLibrary.prototype.getCampaignStatsPacket = function() {
  7130          return UIModel.getInstance().campaignStatsPacket;
  7131      };
  7132      /**
  7133       * Get packet received on successful Login
  7134       * @memberof AgentLibrary.Core.Requests
  7135       * @returns {object}
  7136       */
  7137      AgentLibrary.prototype.getLoginPacket = function() {
  7138          return UIModel.getInstance().loginPacket;
  7139      };
  7140      /**
  7141       * Get packet received on successful Configuration (2nd layer login)
  7142       * @memberof AgentLibrary.Core.Requests
  7143       * @returns {object}
  7144       */
  7145      AgentLibrary.prototype.getConfigPacket = function() {
  7146          return UIModel.getInstance().configPacket;
  7147      };
  7148      /**
  7149       * Get latest received packet for Agent State
  7150       * @memberof AgentLibrary.Core.Requests
  7151       * @returns {object}
  7152       */
  7153      AgentLibrary.prototype.getAgentStatePacket = function() {
  7154          return UIModel.getInstance().agentStatePacket;
  7155      };
  7156      /**
  7157       * Get latest received packet for the Current Call
  7158       * @memberof AgentLibrary.Core.Requests
  7159       * @returns {object}
  7160       */
  7161      AgentLibrary.prototype.getCurrentCallPacket = function() {
  7162          return UIModel.getInstance().currentCallPacket;
  7163      };
  7164      /**
  7165       * Get latest received packet for initiating an offhook session
  7166       * @memberof AgentLibrary.Core.Requests
  7167       * @returns {object}
  7168       */
  7169      AgentLibrary.prototype.getOffhookInitPacket = function() {
  7170          return UIModel.getInstance().offhookInitPacket;
  7171      };
  7172      /**
  7173       * Get latest received packet for terminating an offhook session
  7174       * @memberof AgentLibrary.Core.Requests
  7175       * @returns {object}
  7176       */
  7177      AgentLibrary.prototype.getOffhookTermPacket = function() {
  7178          return UIModel.getInstance().offhookTermPacket;
  7179      };
  7180      /**
  7181       * Get chat agent end request class
  7182       * @memberof AgentLibrary.Core.Requests
  7183       * @returns {object}
  7184       */
  7185      AgentLibrary.prototype.getChatAgentEnd = function(){
  7186          return UIModel.getInstance().chatAgentEnd;
  7187      };
  7188      AgentLibrary.prototype.getChatListRequest = function(){
  7189          return UIModel.getInstance().chatListRequest;
  7190      };
  7191      /**
  7192       * @namespace Notifications
  7193       * @memberof AgentLibrary.Core
  7194       */
  7195      ///////////////////
  7196      // notifications //
  7197      ///////////////////
  7198      /**
  7199       * Get Dial Group Change notification class
  7200       * @memberof AgentLibrary.Core.Notifications
  7201       * @returns {object}
  7202       */
  7203      AgentLibrary.prototype.getDialGroupChangeNotification = function() {
  7204          return UIModel.getInstance().dialGroupChangeNotification;
  7205      };
  7206      /**
  7207       * Get Dial Group Change Pending notification class
  7208       * @memberof AgentLibrary.Core.Notifications
  7209       * @returns {object}
  7210       */
  7211      AgentLibrary.prototype.getDialGroupChangePendingNotification = function() {
  7212          return UIModel.getInstance().dialGroupChangePendingNotification;
  7213      };
  7214      /**
  7215       * Get End Call notification class
  7216       * @memberof AgentLibrary.Core.Notifications
  7217       * @returns {object}
  7218       */
  7219      AgentLibrary.prototype.getEndCallNotification = function() {
  7220          return UIModel.getInstance().endCallNotification;
  7221      };
  7222      /**
  7223       * Get Gates Change notification class
  7224       * @memberof AgentLibrary.Core.Notifications
  7225       * @returns {object}
  7226       */
  7227      AgentLibrary.prototype.getGatesChangeNotification = function() {
  7228          return UIModel.getInstance().gatesChangeNotification;
  7229      };
  7230      /**
  7231       * Get Generic notification class
  7232       * @memberof AgentLibrary.Core.Notifications
  7233       * @returns {object}
  7234       */
  7235      AgentLibrary.prototype.getGenericNotification = function() {
  7236          return UIModel.getInstance().genericNotification;
  7237      };
  7238      /**
  7239       * Get New Call notification class
  7240       * @memberof AgentLibrary.Core.Notifications
  7241       * @returns {object}
  7242       */
  7243      AgentLibrary.prototype.getNewCallNotification = function() {
  7244          return UIModel.getInstance().newCallNotification;
  7245      };
  7246      /**
  7247       * Get current call object
  7248       * @memberof AgentLibrary.Core.Notifications
  7249       * @returns {object}
  7250       */
  7251      AgentLibrary.prototype.getCurrentCall = function() {
  7252          return UIModel.getInstance().currentCall;
  7253      };
  7254      /**
  7255       * Get Add Session notification class
  7256       * @memberof AgentLibrary.Core.Notifications
  7257       * @returns {object}
  7258       */
  7259      AgentLibrary.prototype.getAddSessionNotification = function() {
  7260          return UIModel.getInstance().addSessionNotification;
  7261      };
  7262      /**
  7263       * Get Drop Session notification class
  7264       * @memberof AgentLibrary.Core.Notifications
  7265       * @returns {object}
  7266       */
  7267      AgentLibrary.prototype.getDropSessionNotification = function() {
  7268          return UIModel.getInstance().dropSessionNotification;
  7269      };
  7270      /**
  7271       * Get Early UII notification class
  7272       * @memberof AgentLibrary.Core.Notifications
  7273       * @returns {object}
  7274       */
  7275      AgentLibrary.prototype.getEarlyUiiNotification = function() {
  7276          return UIModel.getInstance().earlyUiiNotification;
  7277      };
  7278      /**
  7279       * Get Chat Active notification class
  7280       * @memberof AgentLibrary.Core.Notifications
  7281       * @returns {object}
  7282       */
  7283      AgentLibrary.prototype.getChatActiveNotification = function() {
  7284          return UIModel.getInstance().chatActiveNotification;
  7285      };
  7286      /**
  7287       * Get Chat Inactive notification class
  7288       * @memberof AgentLibrary.Core.Notifications
  7289       * @returns {object}
  7290       */
  7291      AgentLibrary.prototype.getChatInactiveNotification = function() {
  7292          return UIModel.getInstance().chatInactiveNotification;
  7293      };
  7294      /**
  7295       * Get Chat Inactive notification class
  7296       * @memberof AgentLibrary.Core.Notifications
  7297       * @returns {object}
  7298       */
  7299      AgentLibrary.prototype.getChatClientReconnectNotification = function(){
  7300          return UIModel.getInstance().chatClientReconnectNotification;
  7301      };
  7302      /**
  7303       * Get Chat Presented notification class
  7304       * @memberof AgentLibrary.Core.Notifications
  7305       * @returns {object}
  7306       */
  7307      AgentLibrary.prototype.getChatPresentedNotification = function() {
  7308          return UIModel.getInstance().chatPresentedNotification;
  7309      };
  7310      /**
  7311       * Get Chat Typing notification class
  7312       * @memberof AgentLibrary.Core.Notifications
  7313       * @returns {object}
  7314       */
  7315      AgentLibrary.prototype.getChatTypingNotification = function() {
  7316          return UIModel.getInstance().chatTypingNotification;
  7317      };
  7318      /**
  7319       * Get New Chat notification class
  7320       * @memberof AgentLibrary.Core.Notifications
  7321       * @returns {object}
  7322       */
  7323      AgentLibrary.prototype.getNewChatNotification = function() {
  7324          return UIModel.getInstance().newChatNotification;
  7325      };
  7326      /**
  7327       * @namespace Settings
  7328       * @memberof AgentLibrary.Core
  7329       */
  7330      //////////////////////
  7331      // settings objects //
  7332      //////////////////////
  7333      /**
  7334       * Get Application Settings object containing the current state of application related data
  7335       * @memberof AgentLibrary.Core.Settings
  7336       * @returns {object}
  7337       */
  7338      AgentLibrary.prototype.getApplicationSettings = function() {
  7339          return UIModel.getInstance().applicationSettings;
  7340      };
  7341      /**
  7342       * Get Chat Settings object containing the current state of chat related data
  7343       * @memberof AgentLibrary.Core.Settings
  7344       * @returns {object}
  7345       */
  7346      AgentLibrary.prototype.getChatSettings = function() {
  7347          return UIModel.getInstance().chatSettings;
  7348      };
  7349      /**
  7350       * Get Connection Settings object containing the current state of connection related data
  7351       * @memberof AgentLibrary.Core.Settings
  7352       * @returns {object}
  7353       */
  7354      AgentLibrary.prototype.getConnectionSettings = function() {
  7355          return UIModel.getInstance().connectionSettings;
  7356      };
  7357      /**
  7358       * Get Inbound Settings object containing the current state of inbound related data
  7359       * @memberof AgentLibrary.Core.Settings
  7360       * @returns {object}
  7361       */
  7362      AgentLibrary.prototype.getInboundSettings = function() {
  7363          return UIModel.getInstance().inboundSettings;
  7364      };
  7365      /**
  7366       * Get Outbound Settings object containing the current state of outbound related data
  7367       * @memberof AgentLibrary.Core.Settings
  7368       * @returns {object}
  7369       */
  7370      AgentLibrary.prototype.getOutboundSettings = function() {
  7371          return UIModel.getInstance().outboundSettings;
  7372      };
  7373      /**
  7374       * Get Agent Settings object containing the current state of agent related data
  7375       * @memberof AgentLibrary.Core.Settings
  7376       * @returns {object}
  7377       */
  7378      AgentLibrary.prototype.getAgentSettings = function() {
  7379          return UIModel.getInstance().agentSettings;
  7380      };
  7381      /**
  7382       * Get Transfer Sessions
  7383       * @memberof AgentLibrary.Core.Settings
  7384       * @returns {object}
  7385       */
  7386      AgentLibrary.prototype.getTransferSessions = function() {
  7387          return UIModel.getInstance().transferSessions;
  7388      };
  7389      AgentLibrary.prototype.getPendingSessions = function() {
  7390          return UIModel.getInstance().pendingNewCallSessions;
  7391      };
  7392      /**
  7393       * Get the Agent Permissions object containing the current state of agent permissions
  7394       * @memberof AgentLibrary.Core.Settings
  7395       * @returns {object}
  7396       */
  7397      AgentLibrary.prototype.getAgentPermissions = function() {
  7398          return UIModel.getInstance().agentPermissions;
  7399      };
  7400      /**
  7401       * @namespace Stats
  7402       * @memberof AgentLibrary.Core
  7403       */
  7404      ///////////////////
  7405      // stats objects //
  7406      ///////////////////
  7407      /**
  7408       * Get the Agent stats object containing the current state of agent stats
  7409       * @memberof AgentLibrary.Core.Settings
  7410       * @returns {object}
  7411       */
  7412      AgentLibrary.prototype.getAgentStats = function() {
  7413          return UIModel.getInstance().agentStats;
  7414      };
  7415      /**
  7416       * Get the Agent Daily stats object containing the current state of agent daily stats
  7417       * @memberof AgentLibrary.Core.Stats
  7418       * @returns {object}
  7419       */
  7420      AgentLibrary.prototype.getAgentDailyStats = function() {
  7421          return UIModel.getInstance().agentDailyStats;
  7422      };
  7423      /**
  7424       * Get the Queue stats object containing the current state of queue stats
  7425       * @memberof AgentLibrary.Core.Stats
  7426       * @returns {object}
  7427       */
  7428      AgentLibrary.prototype.getQueueStats = function() {
  7429          return UIModel.getInstance().queueStats;
  7430      };
  7431      /**
  7432       * Get the Chat Queue stats object containing the current state of chat queue stats
  7433       * @memberof AgentLibrary.Core.Stats
  7434       * @returns {object}
  7435       */
  7436      AgentLibrary.prototype.getChatQueueStats = function() {
  7437          return UIModel.getInstance().chatQueueStats;
  7438      };
  7439      /**
  7440       * Get the Campaign stats object containing the current state of campaign stats
  7441       * @memberof AgentLibrary.Core.Stats
  7442       * @returns {object}
  7443       */
  7444      AgentLibrary.prototype.getCampaignStats = function() {
  7445          return UIModel.getInstance().campaignStats;
  7446      };
  7447      /**********************
  7448       *  PRIVATE FUNCTIONS *
  7449       **********************/
  7450      AgentLibrary.prototype._utils = utils;
  7451      AgentLibrary.prototype._NewCallUtils = NewCallUtils;
  7452      AgentLibrary.prototype._getUIModel= function() {
  7453          return UIModel;
  7454      };
  7455  }
  7456  function initAgentLibrarySocket (context) {
  7457      'use strict';
  7458      var AgentLibrary = context.AgentLibrary;
  7459      AgentLibrary.prototype.openSocket = function(callback){
  7460          var instance = this;
  7461          utils.setCallback(instance, CALLBACK_TYPES.OPEN_SOCKET, callback);
  7462          if("WebSocket" in context){
  7463              if(!instance.socket){
  7464                  var socketDest = UIModel.getInstance().applicationSettings.socketDest;
  7465                  utils.logMessage(LOG_LEVELS.DEBUG, "Attempting to open socket connection to " + socketDest, "");
  7466                  instance.socket = new WebSocket(socketDest);
  7467                  instance.socket.onopen = function() {
  7468                      UIModel.getInstance().applicationSettings.socketConnected = true;
  7469                      utils.fireCallback(instance, CALLBACK_TYPES.OPEN_SOCKET, {reconnect:instance._isReconnect});
  7470                      instance.socketOpened();
  7471                  };
  7472                  
  7473                  instance.socket.onmessage = function(evt){
  7474                      var data = JSON.parse(evt.data);
  7475                      if(data.ui_response){
  7476                          utils.processResponse(instance, data);
  7477                      }else if(data.ui_notification){
  7478                          utils.processNotification(instance, data);
  7479                      }else if(data.dialer_request){
  7480                          utils.processDialerResponse(instance, data);
  7481                      }else if(data.ui_stats){
  7482                          utils.processStats(instance, data);
  7483                      }else if(data.ui_request){
  7484                          utils.processRequest(instance, data);
  7485                      }
  7486                  };
  7487                  instance.socket.onclose = function(){
  7488                      utils.fireCallback(instance, CALLBACK_TYPES.CLOSE_SOCKET, '');
  7489                      UIModel.getInstance().applicationSettings.socketConnected = false;
  7490                      instance.socket = null;
  7491                      // cancel daily stats timer
  7492                      clearInterval(UIModel.getInstance().agentDailyIntervalId);
  7493                      UIModel.getInstance().agentDailyIntervalId = null;
  7494                      // cancel stats timer
  7495                      clearInterval(UIModel.getInstance().statsIntervalId);
  7496                      UIModel.getInstance().statsIntervalId = null;
  7497                      // if we are still logged in, set reconnect flag and try to reconnect
  7498                      if(UIModel.getInstance().agentSettings.isLoggedIn){
  7499                          instance._isReconnect = true;
  7500                          console.warn("AgentLibrary: WebSocket is not connected, attempting to reconnect.");
  7501                          setTimeout(function(){
  7502                              instance.openSocket();
  7503                          }, 5000);
  7504                      }
  7505                  };
  7506              }
  7507          }else{
  7508              utils.logMessage(LOG_LEVELS.WARN, "WebSocket NOT supported by your Browser", "");
  7509          }
  7510      };
  7511      AgentLibrary.prototype.closeSocket = function(){
  7512          this.socket.close();
  7513      };
  7514      // when socket is successfully opened, check to see if there are any queued messaged
  7515      // and if so, send them.
  7516      AgentLibrary.prototype.socketOpened = function(){
  7517          var instance = this;
  7518          var currDts = new Date();
  7519          var threeMins = 3 * 60 * 1000; // milliseconds
  7520          var queuedMsg;
  7521          // if this is a reconnect, we need to re-authenticate with IntelliServices & IntelliQueue
  7522          if(instance._isReconnect){
  7523              instance._isReconnect = false;
  7524              // Add IntelliQueue reconnect
  7525              var configRequest = JSON.parse(UIModel.getInstance().configRequest.formatJSON());
  7526              var hashCode = UIModel.getInstance().connectionSettings.hashCode;
  7527              configRequest.ui_request.hash_code = {
  7528                  "#text":hashCode
  7529              };
  7530              configRequest.ui_request.update_login = {
  7531                  "#text": "FALSE"
  7532              };
  7533              configRequest.ui_request.reconnect = {
  7534                  "#text": "TRUE"
  7535              };
  7536              instance._queuedMsgs.unshift({dts: new Date(), msg: JSON.stringify(configRequest)});
  7537              // Add IntelliServices reconnect
  7538              var loginRequest = JSON.parse(UIModel.getInstance().loginRequest.formatJSON());
  7539              var agentId = UIModel.getInstance().agentSettings.agentId;
  7540              loginRequest.ui_request.reconnect = {
  7541                  "#text":"TRUE"
  7542              };
  7543              loginRequest.ui_request.agent_id = {
  7544                  "#text": utils.toString(agentId)
  7545              };
  7546              instance._queuedMsgs.unshift({dts: new Date(), msg: JSON.stringify(loginRequest)});
  7547          }
  7548          for(var idx=0; idx < instance._queuedMsgs.length; idx++){
  7549              queuedMsg = instance._queuedMsgs[idx];
  7550              if(currDts.getTime() - queuedMsg.dts.getTime() < threeMins){
  7551                  // message queued less than 3 mins ago, send
  7552                  utils.logMessage(LOG_LEVELS.DEBUG, "Sending queued message to IntelliSocket.", queuedMsg.msg);
  7553                  utils.sendMessage(instance,queuedMsg.msg);
  7554              }else{
  7555                  // message expired, don't send
  7556                  utils.logMessage(LOG_LEVELS.DEBUG, "Queued message expired, discarding.", queuedMsg.msg);
  7557              }
  7558          }
  7559          // reset queued messages
  7560          instance._queuedMsgs = [];
  7561      };
  7562  }
  7563  function initAgentLibraryAgent (context) {
  7564      /**
  7565       * @namespace Agent
  7566       * @memberof AgentLibrary
  7567       */
  7568      'use strict';
  7569      var AgentLibrary = context.AgentLibrary;
  7570      /**
  7571       * Sends agent login message to IntelliServices
  7572       * @memberof AgentLibrary.Agent
  7573       * @param {string} username Agent's username
  7574       * @param {string} password Agent's password
  7575       * @param {function} [callback=null] Callback function when loginAgent response received
  7576       */
  7577      AgentLibrary.prototype.loginAgent = function(username, password, callback){
  7578          UIModel.getInstance().loginRequest = new LoginRequest(username, password);
  7579          var msg = UIModel.getInstance().loginRequest.formatJSON();
  7580          utils.setCallback(this, CALLBACK_TYPES.LOGIN, callback);
  7581          utils.sendMessage(this, msg);
  7582      };
  7583      /**
  7584       * Sends agent login message to IntelliServices, with flag to tell IntelliServices
  7585       * that agent password is to be treated as case sensitive
  7586       * @memberof AgentLibrary.Agent
  7587       * @param {string} username Agent's username
  7588       * @param {string} password Agent's password
  7589       * @param {function} [callback=null] Callback function when loginAgent response received
  7590       */
  7591      AgentLibrary.prototype.loginAgentCaseSensitive = function(username, password, callback){
  7592          UIModel.getInstance().loginRequest = new LoginRequest(username, password, true);
  7593          var msg = UIModel.getInstance().loginRequest.formatJSON();
  7594          utils.setCallback(this, CALLBACK_TYPES.LOGIN, callback);
  7595          utils.sendMessage(this, msg);
  7596      };
  7597      /**
  7598       * Sends agent configure message (2nd layer login) to IntelliQueue
  7599       * @memberof AgentLibrary.Agent
  7600       * @param {string} dialDest The agent's number, sip | DID.
  7601       * @param {string[]} [queueIds=null] The queue ids the agent will be logged into.
  7602       * @param {string[]} [chatIds=null] The chat ids the agent will be logged into.
  7603       * @param {string} [skillProfileId=null] The skill profile the agent will be logged into.
  7604       * @param {string} [dialGroupId=null] The outbound dial group id the agent will be logged into.
  7605       * @param {string} [updateFromAdminUI=false] Whether the request is generated from the AdminUI or not.
  7606       * @param {boolean} isForce Whether the agent login is forcing an existing agentlogin out.
  7607       * @param {function} [callback=null] Callback function when configureAgent response received.
  7608       */
  7609      AgentLibrary.prototype.configureAgent = function(dialDest, queueIds, chatIds, skillProfileId, dialGroupId, updateFromAdminUI, isForce, callback){
  7610          UIModel.getInstance().configRequest = new ConfigRequest(dialDest, queueIds, chatIds, skillProfileId, dialGroupId, updateFromAdminUI, isForce);
  7611          var msg = UIModel.getInstance().configRequest.formatJSON();
  7612          utils.setCallback(this, CALLBACK_TYPES.CONFIG, callback);
  7613          utils.sendMessage(this, msg);
  7614      };
  7615      /**
  7616       * Sends agent logout message to IntelliQueue
  7617       * @memberof AgentLibrary.Agent
  7618       * @param {number} agentId Id of the agent that will be logged out.
  7619       * @param {function} [callback=null] Callback function when logoutAgent response received.
  7620       */
  7621      AgentLibrary.prototype.logoutAgent = function(agentId, callback){
  7622          UIModel.getInstance().logoutRequest = new LogoutRequest(agentId);
  7623          utils.setCallback(this, CALLBACK_TYPES.LOGOUT, callback);
  7624          UIModel.getInstance().agentSettings.isLoggedIn = false;
  7625          // Agent requested logout, just close socket??
  7626          utils.fireCallback(this, CALLBACK_TYPES.LOGOUT, "");
  7627          this.closeSocket();
  7628      };
  7629      /**
  7630       * Sends agent logout for the given agent to logout message to IntelliQueue
  7631       * @memberof AgentLibrary.Agent
  7632       * @param {number} agentToLogout Id of the agent that will be logged out.
  7633       * @param {number} [requestMessage=""] Message to send for the logout request.
  7634       * @param {function} [callback=null] Callback function when logoutAgent response received.
  7635       */
  7636      AgentLibrary.prototype.requestLogoutAgent = function(agentToLogout, requestMessage, callback){
  7637          var isSupervisor = UIModel.getInstance().agentSettings.agentType === 'SUPERVISOR';
  7638          UIModel.getInstance().logoutRequest = new LogoutRequest(agentToLogout, requestMessage, isSupervisor);
  7639          utils.setCallback(this, CALLBACK_TYPES.LOGOUT, callback);
  7640          if(UIModel.getInstance().logoutRequest.isSupervisor){
  7641              //This is a supervisor request to log an agent out. Create the
  7642              //logout packet and then send the packet to IntelliQueue.
  7643              var msg = UIModel.getInstance().logoutRequest.formatJSON();
  7644              utils.sendMessage(this, msg);
  7645          }
  7646      };
  7647      /**
  7648       * Sends agent state change message to IntelliQueue
  7649       * @memberof AgentLibrary.Agent
  7650       * @param {string} agentState The system/base state to transition to <br />
  7651       * AVAILABLE | TRANSITION | ENGAGED | ON-BREAK | WORKING | AWAY | LUNCH | AUX-UNAVAIL-NO-OFFHOOK | AUX-UNAVAIL-OFFHOOK
  7652       * @param {string} [agentAuxState=""] The aux state display label
  7653       * @param {function} [callback=null] Callback function when agentState response received
  7654       */
  7655      AgentLibrary.prototype.setAgentState = function(agentState, agentAuxState, callback){
  7656          UIModel.getInstance().agentStateRequest = new AgentStateRequest(agentState, agentAuxState);
  7657          var msg = UIModel.getInstance().agentStateRequest.formatJSON();
  7658          utils.setCallback(this, CALLBACK_TYPES.AGENT_STATE, callback);
  7659          utils.sendMessage(this, msg);
  7660      };
  7661      /**
  7662       * Initiates an agent offhook session
  7663       * @memberof AgentLibrary.Agent
  7664       * @param {function} [callback=null] Callback function when offhookInit response received
  7665       */
  7666      AgentLibrary.prototype.offhookInit = function(callback){
  7667          UIModel.getInstance().offhookInitRequest = new OffhookInitRequest();
  7668          var msg = UIModel.getInstance().offhookInitRequest.formatJSON();
  7669          utils.setCallback(this, CALLBACK_TYPES.OFFHOOK_INIT, callback);
  7670          utils.sendMessage(this, msg);
  7671      };
  7672      /**
  7673       * Terminates agent's offhook session
  7674       * @memberof AgentLibrary.Agent
  7675       * @param {function} [callback=null] Callback function when pending callbacks response received
  7676       */
  7677      AgentLibrary.prototype.offhookTerm = function(callback){
  7678          UIModel.getInstance().offhookTermRequest = new OffhookTermRequest();
  7679          var msg = UIModel.getInstance().offhookTermRequest.formatJSON();
  7680          utils.setCallback(this, CALLBACK_TYPES.OFFHOOK_TERM, callback);
  7681          utils.sendMessage(this, msg);
  7682      };
  7683      /**
  7684       * Returns scheduled callbacks for the given agent
  7685       * @memberof AgentLibrary.Agent
  7686       * @param {number} [agentId=logged in agent id] Id of agent to get callbacks for
  7687       * @param {function} [callback=null] Callback function when pending callbacks response received
  7688       */
  7689      AgentLibrary.prototype.getPendingCallbacks = function(agentId, callback){
  7690          UIModel.getInstance().callbacksPendingRequest = new CallbacksPendingRequest(agentId);
  7691          var msg = UIModel.getInstance().callbacksPendingRequest.formatJSON();
  7692          utils.setCallback(this, CALLBACK_TYPES.CALLBACK_PENDING, callback);
  7693          utils.sendMessage(this, msg);
  7694      };
  7695      /**
  7696       * Cancel a scheduled callback for the given agent based on lead id
  7697       * @memberof AgentLibrary.Agent
  7698       * @param {number} leadId Id of lead callback to cancel
  7699       * @param {number} [agentId=logged in agent id] Id of agent to cancel specified lead callback for
  7700       * @param {function} [callback=null] Callback function when callback is canceled
  7701       */
  7702      AgentLibrary.prototype.cancelCallback = function(leadId, agentId, callback){
  7703          UIModel.getInstance().callbackCancelRequest = new CallbackCancelRequest(leadId, agentId);
  7704          var msg = UIModel.getInstance().callbackCancelRequest.formatJSON();
  7705          utils.setCallback(this, CALLBACK_TYPES.CALLBACK_CANCEL, callback);
  7706          utils.sendMessage(this, msg);
  7707      };
  7708      /**
  7709       * Request stats messages to be sent every 5 seconds. The stats responses will be sent as
  7710       * four possible callback types: agentStats, agentDailyStats, campaignStats, or queueStats
  7711       * @memberof AgentLibrary.Agent
  7712       */
  7713      AgentLibrary.prototype.requestStats = function(){
  7714          // start stats interval timer, request stats every 5 seconds
  7715          if(UIModel.getInstance().statsIntervalId === null) {
  7716              UIModel.getInstance().statsIntervalId = setInterval(utils.sendStatsRequestMessage, 5000);
  7717          }
  7718      };
  7719      /**
  7720       * Terminate stats messages sent to the agent every 5 seconds.
  7721       * @memberof AgentLibrary.Agent
  7722       */
  7723      AgentLibrary.prototype.terminateStats = function(){
  7724          clearInterval(UIModel.getInstance().statsIntervalId);
  7725          UIModel.getInstance().statsIntervalId = null;
  7726      };
  7727      /**
  7728       * Set the agent dial destination
  7729       * @memberof AgentLibrary.Agent
  7730       * @param {string} dialDest The dial destination used for softphone registration
  7731       * @param {boolean} isSoftphoneError True - if we want to log this dial destination update as a softphone error
  7732       */
  7733      AgentLibrary.prototype.updateDialDestination = function(dialDest, isSoftphoneError){
  7734          UIModel.getInstance().updateDialDestinationRequest = new UpdateDialDestinationRequest(dialDest, isSoftphoneError);
  7735          var msg = UIModel.getInstance().updateDialDestinationRequest.formatJSON();
  7736          utils.sendMessage(this, msg);
  7737      };
  7738  }
  7739  function initAgentLibraryCall (context) {
  7740      /**
  7741       * @namespace Call
  7742       * @memberof AgentLibrary
  7743       */
  7744      'use strict';
  7745      var AgentLibrary = context.AgentLibrary;
  7746      /**
  7747       * Barge in on a call, can hear all parties and be heard by all
  7748       * @memberof AgentLibrary.Call
  7749       * @param {number} agentId Agent Id of the current logged in agent
  7750       * @param {string} uii UII of the active call you wish to monitor
  7751       * @param {number} monitorAgentId UII Agent Id of the agent you wish to monitor
  7752       * @param {function} [callback=null] Callback function when barge in response received
  7753       */
  7754      AgentLibrary.prototype.bargeIn = function(agentId, uii, monitorAgentId, callback){
  7755          UIModel.getInstance().bargeInRequest = new BargeInRequest("FULL", agentId, uii, monitorAgentId);
  7756          var msg = UIModel.getInstance().bargeInRequest.formatJSON();
  7757          utils.setCallback(this, CALLBACK_TYPES.BARGE_IN, callback);
  7758          utils.sendMessage(this, msg);
  7759      };
  7760      /**
  7761       * Add a coaching session to the call, can hear all parties but only able to speak on agent channel
  7762       * @memberof AgentLibrary.Call
  7763       * @param {number} agentId Agent Id of the current logged in agent
  7764       * @param {string} uii UII of the active call you wish to monitor
  7765       * @param {number} monitorAgentId UII Agent Id of the agent you wish to monitor
  7766       * @param {function} [callback=null] Callback function when coaching session response received
  7767       */
  7768      AgentLibrary.prototype.coach = function(agentId, uii, monitorAgentId, callback){
  7769          UIModel.getInstance().bargeInRequest = new BargeInRequest("COACHING", agentId, uii, monitorAgentId);
  7770          var msg = UIModel.getInstance().bargeInRequest.formatJSON();
  7771          utils.setCallback(this, CALLBACK_TYPES.COACH_CALL, callback);
  7772          utils.sendMessage(this, msg);
  7773      };
  7774      /**
  7775       * Transfer to another number and end the call for the original agent (cold transfer).
  7776       * @memberof AgentLibrary.Call
  7777       * @param {number} dialDest Number to transfer to
  7778       * @param {number} [callerId=""] Caller Id for caller (DNIS)
  7779       * @param {number} [sipHeaders=[]] Name/Value header pairs
  7780       * @param {function} [callback=null] Callback function when cold transfer response received
  7781       */
  7782      AgentLibrary.prototype.coldXfer = function(dialDest, callerId, sipHeaders, callback){
  7783          UIModel.getInstance().coldXferRequest = new XferColdRequest(dialDest, callerId, sipHeaders);
  7784          var msg = UIModel.getInstance().coldXferRequest.formatJSON();
  7785          utils.setCallback(this, CALLBACK_TYPES.XFER_COLD, callback);
  7786          utils.sendMessage(this, msg);
  7787      };
  7788      /**
  7789       * Transfer to another number and end the call for the original agent (cold transfer).
  7790       * @memberof AgentLibrary.Call
  7791       * @param {number} dialDest Number to transfer to
  7792       * @param {number} [callerId=""] Caller Id for caller (DNIS)
  7793       * @param {number} [sipHeaders=[]] Name/Value header pairs
  7794       * @param {number} [countryId=""] Country Id for the dialDest
  7795       * @param {function} [callback=null] Callback function when warm transfer response received
  7796       */
  7797      AgentLibrary.prototype.internationalColdXfer = function(dialDest, callerId, sipHeaders, countryId, callback){
  7798          UIModel.getInstance().coldXferRequest = new XferColdRequest(dialDest, callerId, sipHeaders, countryId);
  7799          var msg = UIModel.getInstance().coldXferRequest.formatJSON();
  7800          utils.setCallback(this, CALLBACK_TYPES.XFER_COLD, callback);
  7801          utils.sendMessage(this, msg);
  7802      };
  7803      /**
  7804       * Send a disposition for an inbound or outbound call
  7805       * @memberof AgentLibrary.Call
  7806       * @param {string} uii UII (unique id) for call
  7807       * @param {string} dispId The disposition id
  7808       * @param {string} notes Agent notes for call
  7809       * @param {boolean} callback Boolean for whether or not this call is a callback
  7810       * @param {string} [callbackDTS=""] date time stamp if callback
  7811       * @param {string} [contactForwardNumber=null] Number for contact forwarding
  7812       * @param {string} [survey=null] The survey response values for the call.
  7813       * Format: survey = [ { label: "", externId: "", leadUpdateColumn: ""} ]
  7814       * @param {string} [externId=null] The external id associated with the lead for this call (only for Outbound Dispositions).
  7815       * @param {string} [leadId=null] The lead id associated with this call (only for Outbound Dispositions).
  7816       * @param {string} [requestId=null] The request id associated with a preview fetched lead (only for Outbound Dispositions).
  7817       */
  7818      AgentLibrary.prototype.dispositionCall = function(uii, dispId, notes, callback, callbackDTS, contactForwardNumber, survey, externId, leadId, requestId){
  7819          var model = UIModel.getInstance();
  7820          model.dispositionRequest = new DispositionRequest(uii, dispId, notes, callback, callbackDTS, contactForwardNumber, survey, externId, leadId, requestId);
  7821          var msg = model.dispositionRequest.formatJSON();
  7822          utils.sendMessage(this, msg);
  7823          // cancel ping call timer
  7824          if(model.pingIntervalId){
  7825              clearInterval(model.pingIntervalId);
  7826              model.pingIntervalId = null;
  7827          }
  7828      };
  7829      /**
  7830       * Send a disposition for a manual pass on a lead
  7831       * @memberof AgentLibrary.Call
  7832       * @param {string} dispId The disposition id
  7833       * @param {string} notes Agent notes for call
  7834       * @param {boolean} callback Boolean for whether or not this call is a callback
  7835       * @param {string} [callbackDTS=""] date time stamp if callback
  7836       * @param {string} [leadId=null] The lead id
  7837       * @param {string} [requestId=null] The request key for the lead
  7838       * @param {string} [externId=null] The external id of the lead
  7839       */
  7840      AgentLibrary.prototype.dispositionManualPass = function(dispId, notes, callback, callbackDTS, leadId, requestId, externId){
  7841          UIModel.getInstance().dispositionManualPassRequest = new DispositionManualPassRequest(dispId, notes, callback, callbackDTS, leadId, requestId, externId);
  7842          var msg = UIModel.getInstance().dispositionManualPassRequest.formatJSON();
  7843          utils.sendMessage(this, msg);
  7844      };
  7845      /**
  7846       * Get a list of all campaign dispositions for given campaign id
  7847       * @memberof AgentLibrary.Call
  7848       * @param {string} campaignId Id for campaign to get dispositions for
  7849       * @param {function} [callback=null] Callback function when campaign dispositions response received
  7850       */
  7851      AgentLibrary.prototype.getCampaignDispositions = function(campaignId, callback){
  7852          UIModel.getInstance().campaignDispositionsRequest = new CampaignDispositionsRequest(campaignId);
  7853          var msg = UIModel.getInstance().campaignDispositionsRequest.formatJSON();
  7854          utils.setCallback(this, CALLBACK_TYPES.CAMPAIGN_DISPOSITIONS, callback);
  7855          utils.sendMessage(this, msg);
  7856      };
  7857      /**
  7858       * Sends a hangup request message
  7859       * @memberof AgentLibrary.Call
  7860       * @param {string} [sessionId=""] Session to hangup, defaults to current call session id
  7861       * @param {boolean} resetPendingDisp, reset pendingDisp to false, in case of bad reconnect
  7862       */
  7863      AgentLibrary.prototype.hangup = function(sessionId, resetPendingDisp){
  7864          UIModel.getInstance().hangupRequest = new HangupRequest(sessionId, resetPendingDisp);
  7865          var msg = UIModel.getInstance().hangupRequest.formatJSON();
  7866          utils.sendMessage(this, msg);
  7867      };
  7868      /**
  7869       * Place a call on hold
  7870       * @memberof AgentLibrary.Call
  7871       * @param {boolean} holdState Whether we are putting call on hold or taking off hold - values true | false
  7872       * @param {function} [callback=null] Callback function when hold response received
  7873       */
  7874      AgentLibrary.prototype.hold = function(holdState, callback){
  7875          UIModel.getInstance().holdRequest = new HoldRequest(holdState);
  7876          var msg = UIModel.getInstance().holdRequest.formatJSON();
  7877          utils.setCallback(this, CALLBACK_TYPES.HOLD, callback);
  7878          utils.sendMessage(this, msg);
  7879      };
  7880      /**
  7881       * Place a specified session of a call on hold
  7882       * @memberof AgentLibrary.Call
  7883       * @param {boolean} holdState Whether we are putting call on hold or taking off hold - values true | false
  7884       * @param {integer|string} sessionId session id of the call to place on hold
  7885       * @param {function} [callback=null] Callback function when hold response received
  7886       */
  7887      AgentLibrary.prototype.holdSession = function(holdState, sessionId, callback){
  7888          UIModel.getInstance().holdRequest = new HoldRequest(holdState, sessionId);
  7889          var msg = UIModel.getInstance().holdRequest.formatJSON();
  7890          utils.setCallback(this, CALLBACK_TYPES.HOLD, callback);
  7891          utils.sendMessage(this, msg);
  7892      };
  7893      /**
  7894       * Sends a manual outdial request message
  7895       * @memberof AgentLibrary.Call
  7896       * @param {string} destination Number to call - ANI
  7897       * @param {number} callerId Number displayed to callee, DNIS
  7898       * @param {number} [ringTime=60] Time in seconds to ring call
  7899       * @param {string} [countryId='USA'] Country for the destination number
  7900       * @param {number} [queueId=''] Queue id to tie manual call to
  7901       */
  7902      AgentLibrary.prototype.manualOutdial = function(destination, callerId, ringTime, countryId, queueId){
  7903          UIModel.getInstance().oneToOneOutdialRequest = new OneToOneOutdialRequest(destination, callerId, ringTime, countryId, queueId);
  7904          var msg = UIModel.getInstance().oneToOneOutdialRequest.formatJSON();
  7905          utils.sendMessage(this, msg);
  7906      };
  7907      /**
  7908       * Cancels a manual outdial request by UII.
  7909       * @memberof AgentLibrary.Call
  7910       * @param {string} uii UII of manual call request, the UII is returned in the EARLY_UII notification.
  7911       */
  7912      AgentLibrary.prototype.manualOutdialCancel = function(uii){
  7913          UIModel.getInstance().oneToOneOutdialCancelRequest = new OneToOneOutdialCancelRequest(uii);
  7914          var msg = UIModel.getInstance().oneToOneOutdialCancelRequest.formatJSON();
  7915          utils.sendMessage(this, msg);
  7916      };
  7917      /**
  7918       * Pause call recording
  7919       * @memberof AgentLibrary.Call
  7920       * @param {boolean} record Whether we are recording or not
  7921       * @param {function} [callback=null] Callback function when pause record response received
  7922       */
  7923      AgentLibrary.prototype.pauseRecord = function(record, callback){
  7924          UIModel.getInstance().pauseRecordRequest = new PauseRecordRequest(record);
  7925          var msg = UIModel.getInstance().pauseRecordRequest.formatJSON();
  7926          utils.setCallback(this, CALLBACK_TYPES.PAUSE_RECORD, callback);
  7927          utils.sendMessage(this, msg);
  7928      };
  7929      /**
  7930       * Sends a preview dial request to call lead based on request id and (optional) lead phone.
  7931       * Call previewFetch method first to get request id.
  7932       * @memberof AgentLibrary.Call
  7933       * @param {number} requestId Pending request id sent back with lead, required to dial lead.
  7934       * @param {number} [leadPhone=""] Lead phone number. Only needed if there are multiple numbers loaded for given lead.
  7935       */
  7936      AgentLibrary.prototype.previewDial = function(requestId, leadPhone){
  7937          UIModel.getInstance().previewDialRequest = new PreviewDialRequest("", [], requestId, leadPhone);
  7938          var msg = UIModel.getInstance().previewDialRequest.formatJSON();
  7939          utils.sendMessage(this, msg);
  7940      };
  7941      /**
  7942       * Sends a message to fetch preview dialable leads
  7943       * @memberof AgentLibrary.Call
  7944       * @param {array} [searchFields=[]] Array of objects with key/value pairs for search parameters
  7945       * e.g. [ {key: "name", value: "Geoff"} ]
  7946       * @param {function} [callback=null] Callback function when preview fetch completed, returns matched leads
  7947       */
  7948      AgentLibrary.prototype.previewFetch = function(searchFields, callback){
  7949          UIModel.getInstance().previewDialRequest = new PreviewDialRequest("", searchFields, "");
  7950          var msg = UIModel.getInstance().previewDialRequest.formatJSON();
  7951          utils.setCallback(this, CALLBACK_TYPES.PREVIEW_FETCH, callback);
  7952          utils.sendMessage(this, msg);
  7953      };
  7954      /**
  7955       * Pull back leads that match search criteria
  7956       * @memberof AgentLibrary.Call
  7957       * @param {array} [searchFields=[]] Array of objects with key/value pairs for search parameters
  7958       * e.g. [ {key: "name", value: "Geoff"} ]
  7959       * @param {function} [callback=null] Callback function when lead search completed, returns matched leads
  7960       */
  7961      AgentLibrary.prototype.searchLeads = function(searchFields, callback){
  7962          UIModel.getInstance().previewDialRequest = new PreviewDialRequest("search", searchFields, "");
  7963          var msg = UIModel.getInstance().previewDialRequest.formatJSON();
  7964          utils.setCallback(this, CALLBACK_TYPES.LEAD_SEARCH, callback);
  7965          utils.sendMessage(this, msg);
  7966      };
  7967      /**
  7968       * Set agent notes for a call
  7969       * @memberof AgentLibrary.Call
  7970       * @param {string} notes Agent notes to add to call
  7971       * @param {function} [callback=null] Callback function when call notes response received
  7972       */
  7973      AgentLibrary.prototype.setCallNotes = function(notes, callback){
  7974          UIModel.getInstance().callNotesRequest = new CallNotesRequest(notes);
  7975          var msg = UIModel.getInstance().callNotesRequest.formatJSON();
  7976          utils.setCallback(this, CALLBACK_TYPES.CALL_NOTES, callback);
  7977          utils.sendMessage(this, msg);
  7978      };
  7979      /**
  7980       * Add a silent monitor session to a call, can hear all channels but can't be heard by any party
  7981       * @memberof AgentLibrary.Call
  7982       * @param {number} agentId Agent Id of the current logged in agent
  7983       * @param {string} uii UII of the active call you wish to monitor
  7984       * @param {number} monitorAgentId UII Agent Id of the agent you wish to monitor
  7985       * @param {function} [callback=null] Callback function when silent monitor response received
  7986       */
  7987      AgentLibrary.prototype.monitor = function(agentId, uii, monitorAgentId, callback){
  7988          UIModel.getInstance().bargeInRequest = new BargeInRequest("MUTE", agentId, uii, monitorAgentId);
  7989          var msg = UIModel.getInstance().bargeInRequest.formatJSON();
  7990          utils.setCallback(this, CALLBACK_TYPES.SILENT_MONITOR, callback);
  7991          utils.sendMessage(this, msg);
  7992      };
  7993      /**
  7994       * Toggle call recording based on passed in boolean true | false
  7995       * @memberof AgentLibrary.Call
  7996       * @param {boolean} record Whether we are recording or not
  7997       * @param {function} [callback=null] Callback function when record response received
  7998       */
  7999      AgentLibrary.prototype.record = function(record, callback){
  8000          UIModel.getInstance().recordRequest = new RecordRequest(record);
  8001          var msg = UIModel.getInstance().recordRequest.formatJSON();
  8002          utils.setCallback(this, CALLBACK_TYPES.RECORD, callback);
  8003          utils.sendMessage(this, msg);
  8004      };
  8005      /**
  8006       * Requeue a call
  8007       * @memberof AgentLibrary.Call
  8008       * @param {number} queueId Queue Id to send the call to
  8009       * @param {number} skillId Skill Id for the requeued call
  8010       * @param {boolean} maintain Whether or not to maintain the current agent
  8011       * @param {function} [callback=null] Callback function when requeue response received
  8012       */
  8013      AgentLibrary.prototype.requeueCall = function(queueId, skillId, maintain, callback){
  8014          UIModel.getInstance().requeueRequest = new RequeueRequest(queueId, skillId, maintain);
  8015          var msg = UIModel.getInstance().requeueRequest.formatJSON();
  8016          utils.setCallback(this, CALLBACK_TYPES.REQUEUE, callback);
  8017          utils.sendMessage(this, msg);
  8018      };
  8019      /**
  8020       * Sends a TCPA Safe call request to call lead based on request id and (optional) lead phone.
  8021       * Call safeModeFetch method first to get request id.
  8022       * @memberof AgentLibrary.Call
  8023       * @param {number} requestId Pending request id sent back with lead, required to dial lead.
  8024       * @param {number} [leadPhone=""] Lead phone number. Only needed if there are multiple numbers loaded for given lead.
  8025       */
  8026      AgentLibrary.prototype.safeModeCall = function(requestId, leadPhone){
  8027          UIModel.getInstance().tcpaSafeRequest = new TcpaSafeRequest("", [], requestId, leadPhone);
  8028          var msg = UIModel.getInstance().tcpaSafeRequest.formatJSON();
  8029          utils.sendMessage(this, msg);
  8030      };
  8031      /**
  8032       * Sends a message to fetch safe mode dialable leads
  8033       * @memberof AgentLibrary.Call
  8034       * @param {array} [searchFields=[]] Array of objects with key/value pairs for search parameters
  8035       * e.g. [ {key: "name", value: "Geoff"} ]
  8036       * @param {function} [callback=null] Callback function when safe mode fetch completed, returns matched leads
  8037       */
  8038      AgentLibrary.prototype.safeModeFetch = function(searchFields, callback){
  8039          UIModel.getInstance().tcpaSafeRequest = new TcpaSafeRequest("", searchFields, "");
  8040          var msg = UIModel.getInstance().tcpaSafeRequest.formatJSON();
  8041          utils.setCallback(this, CALLBACK_TYPES.SAFE_MODE_FETCH, callback);
  8042          utils.sendMessage(this, msg);
  8043      };
  8044      /**
  8045       * Pull back Safe Mode leads that match search criteria
  8046       * @memberof AgentLibrary.Call
  8047       * @param {array} [searchFields=[]] Array of objects with key/value pairs for search parameters
  8048       * e.g. [ {key: "name", value: "Geoff"} ]
  8049       * @param {function} [callback=null] Callback function when safe mode fetch completed, returns matched leads
  8050       */
  8051      AgentLibrary.prototype.safeSearchLeads = function(searchFields, callback){
  8052          UIModel.getInstance().tcpaSafeRequest = new TcpaSafeRequest("search", searchFields, "");
  8053          var msg = UIModel.getInstance().tcpaSafeRequest.formatJSON();
  8054          utils.setCallback(this, CALLBACK_TYPES.SAFE_MODE_SEARCH, callback);
  8055          utils.sendMessage(this, msg);
  8056      };
  8057      /**
  8058       * Transfer to another number while keeping the original agent on the line (warm transfer).
  8059       * @memberof AgentLibrary.Call
  8060       * @param {number} dialDest Number to transfer to
  8061       * @param {number} [callerId=""] Caller Id for caller (DNIS)
  8062       * @param {number} [sipHeaders=[]] Name/Value header pairs
  8063       * @param {number} [countryId=""] Country Id for the dialDest
  8064       * @param {function} [callback=null] Callback function when warm transfer response received
  8065       */
  8066      AgentLibrary.prototype.internationalWarmXfer = function(dialDest, callerId, sipHeaders, countryId, callback){
  8067          UIModel.getInstance().warmXferRequest = new XferWarmRequest(dialDest, callerId, sipHeaders, countryId);
  8068          var msg = UIModel.getInstance().warmXferRequest.formatJSON();
  8069          utils.setCallback(this, CALLBACK_TYPES.XFER_WARM, callback);
  8070          utils.sendMessage(this, msg);
  8071      };
  8072      /**
  8073       * Transfer to another number while keeping the original agent on the line (warm transfer).
  8074       * @memberof AgentLibrary.Call
  8075       * @param {number} dialDest Number to transfer to
  8076       * @param {number} [callerId=""] Caller Id for caller (DNIS)
  8077       * @param {number} [sipHeaders=[]] Name/Value header pairs
  8078       * @param {function} [callback=null] Callback function when warm transfer response received
  8079       */
  8080      AgentLibrary.prototype.warmXfer = function(dialDest, callerId, sipHeaders, callback){
  8081          UIModel.getInstance().warmXferRequest = new XferWarmRequest(dialDest, callerId, sipHeaders);
  8082          var msg = UIModel.getInstance().warmXferRequest.formatJSON();
  8083          utils.setCallback(this, CALLBACK_TYPES.XFER_WARM, callback);
  8084          utils.sendMessage(this, msg);
  8085      };
  8086      /**
  8087       * Cancel a warm transfer
  8088       * @memberof AgentLibrary.Call
  8089       * @param {number} dialDest Number that was transfered to
  8090       */
  8091      AgentLibrary.prototype.warmXferCancel = function(dialDest){
  8092          UIModel.getInstance().warmXferCancelRequest = new XferWarmCancelRequest(dialDest);
  8093          var msg = UIModel.getInstance().warmXferCancelRequest.formatJSON();
  8094          utils.sendMessage(this, msg);
  8095      };
  8096      /**
  8097       * Requests a script object based on given id
  8098       * @memberof AgentLibrary.Call
  8099       * @param {number} scriptId Id of script
  8100       * @param {number} version The version number of the script, if the current loaded script version matches,
  8101       *                 just return current script. Otherwise, fetch new version of script.
  8102       * @param {function} [callback=null] Callback function when warm transfer response received
  8103       */
  8104      AgentLibrary.prototype.getScript = function(scriptId, version, callback){
  8105          var model = UIModel.getInstance();
  8106          var script = model.scriptSettings.loadedScripts[scriptId];
  8107          utils.setCallback(this, CALLBACK_TYPES.SCRIPT_CONFIG, callback);
  8108          if(script && script.version === version){
  8109              // return from memory
  8110              var savedScript = UIModel.getInstance().scriptSettings.loadedScripts[scriptId];
  8111              callback(savedScript);
  8112          }else{
  8113              // load script
  8114              model.scriptConfigRequest = new ScriptConfigRequest(scriptId);
  8115              var msg = UIModel.getInstance().scriptConfigRequest.formatJSON();
  8116              utils.sendMessage(this, msg);
  8117          }
  8118      };
  8119      /**
  8120       * Saves the results from a script
  8121       * @memberof AgentLibrary.Call
  8122       * @param {string} uii The UII of the call the script results belong to
  8123       * @param {number} scriptId Id of script
  8124       * @param {object} jsonResult JSON object of script results, name/value pairs
  8125       */
  8126      AgentLibrary.prototype.saveScriptResult = function(uii, scriptId, jsonResult){
  8127          UIModel.getInstance().scriptResultRequest = new ScriptResultRequest(uii, scriptId, jsonResult);
  8128          var msg = UIModel.getInstance().scriptResultRequest.formatJSON();
  8129          utils.sendMessage(this, msg);
  8130      };
  8131      /**
  8132       * Get available list of agents available for Direct Transfer
  8133       * @memberof AgentLibrary.Call
  8134       */
  8135      AgentLibrary.prototype.directAgentXferList = function(callback) {
  8136          UIModel.getInstance().directAgentTransferListRequest = new DirectAgentTransferList();
  8137          var msg = UIModel.getInstance().directAgentTransferListRequest.formatJSON();
  8138          utils.setCallback(this, CALLBACK_TYPES.DIRECT_AGENT_TRANSFER_LIST, callback);
  8139          utils.sendMessage(this, msg);
  8140      };
  8141      /**
  8142       * Transfer directly to an available agent from the directAgentXferList result and stay on the call
  8143       * @memberof AgentLibrary.Call
  8144       * @param {number} targetAgentId Agent id to transfer the call to
  8145       */
  8146      AgentLibrary.prototype.warmDirectAgentXfer = function(targetAgentId) {
  8147          UIModel.getInstance().directAgentTransferRequest = new DirectAgentTransfer(targetAgentId, 'WARM');
  8148          var msg = UIModel.getInstance().directAgentTransferRequest.formatJSON();
  8149          utils.sendMessage(this, msg);
  8150      };
  8151      /**
  8152       * Transfer directly to an available agent from the directAgentXferList result
  8153       * and terminate the current agents call session
  8154       * @memberof AgentLibrary.Call
  8155       * @param {number} targetAgentId Agent id to transfer the call to
  8156       */
  8157      AgentLibrary.prototype.coldDirectAgentXfer = function(targetAgentId) {
  8158          UIModel.getInstance().directAgentTransferRequest = new DirectAgentTransfer(targetAgentId, 'COLD');
  8159          var msg = UIModel.getInstance().directAgentTransferRequest.formatJSON();
  8160          utils.sendMessage(this, msg);
  8161      };
  8162      /**
  8163       * Cancel the request to transfer directly to an agent
  8164       * @memberof AgentLibrary.Call
  8165       * @param {number} targetAgentId Agent id to transfer the call to
  8166       */
  8167      AgentLibrary.prototype.cancelDirectAgentXfer = function(targetAgentId) {
  8168          UIModel.getInstance().directAgentTransferRequest = new DirectAgentTransfer(targetAgentId, 'CANCEL');
  8169          var msg = UIModel.getInstance().directAgentTransferRequest.formatJSON();
  8170          utils.sendMessage(this, msg);
  8171      };
  8172     /**
  8173      * Send the direct agent transfer straight to voicemail, avoid any attempts to connect to the target agent
  8174      * @memberof AgentLibrary.Call
  8175      * @param {number} targetAgentId Agent id to receive the voicemail
  8176      */
  8177      AgentLibrary.prototype.voicemailDirectAgentXfer = function(targetAgentId) {
  8178          UIModel.getInstance().directAgentTransferRequest = new DirectAgentTransfer(targetAgentId, 'VOICEMAIL');
  8179          var msg = UIModel.getInstance().directAgentTransferRequest.formatJSON();
  8180          utils.sendMessage(this, msg);
  8181      };
  8182      /**
  8183       * Reject a presented direct agent transfer, if WARM requesting agent will be notified to try again,
  8184       * if COLD a voicemail will be left for the target agent
  8185       * @memberof AgentLibrary.Call
  8186       * @param {number} targetAgentId Agent id to receive the voicemail
  8187       */
  8188      AgentLibrary.prototype.rejectDirectAgentXfer = function(uii) {
  8189          UIModel.getInstance().directAgentTransferRequest = new DirectAgentTransfer('0', 'REJECT', uii);
  8190          var msg = UIModel.getInstance().directAgentTransferRequest.formatJSON();
  8191          utils.sendMessage(this, msg);
  8192      };
  8193  }
  8194  function initAgentLibraryLead (context) {
  8195      /**
  8196       * @namespace Lead
  8197       * @memberof AgentLibrary
  8198       */
  8199      
  8200      'use strict';
  8201      var AgentLibrary = context.AgentLibrary;
  8202      /**
  8203       * Get the history for a given lead
  8204       * @memberof AgentLibrary.Lead
  8205       * @param {number} leadId The lead id to retrieve history for
  8206       * @param {function} [callback=null] Callback function when lead history response received
  8207       */
  8208      AgentLibrary.prototype.leadHistory = function(leadId, callback){
  8209          UIModel.getInstance().leadHistoryRequest = new LeadHistoryRequest(leadId);
  8210          var msg = UIModel.getInstance().leadHistoryRequest.formatJSON();
  8211          utils.setCallback(this, CALLBACK_TYPES.LEAD_HISTORY, callback);
  8212          utils.sendMessage(this, msg);
  8213      };
  8214      /**
  8215       * Insert a lead to the given campaign
  8216       * @memberof AgentLibrary.Lead
  8217       * @param {object} dataObj agentId, campaignId, and lead info
  8218       * @param {function} [callback=null] Callback function when lead history response received
  8219       */
  8220      AgentLibrary.prototype.leadInsert = function(dataObj, callback){
  8221          UIModel.getInstance().leadInsertRequest = new LeadInsertRequest(dataObj);
  8222          var msg = UIModel.getInstance().leadInsertRequest.formatJSON();
  8223          utils.setCallback(this, CALLBACK_TYPES.LEAD_INSERT, callback);
  8224          utils.sendMessage(this, msg);
  8225      };
  8226      /**
  8227       * Update lead information
  8228       * @memberof AgentLibrary.Lead
  8229       * @param {string} leadId Id for lead to update
  8230       * @param {string} leadPhone Lead phone number
  8231       * @param {object} baggage Object containing lead information
  8232       * @param {function} [callback=null] Callback function when lead history response received
  8233       */
  8234      AgentLibrary.prototype.leadUpdate = function(leadId, leadPhone, baggage, callback){
  8235          UIModel.getInstance().leadUpdateRequest = new LeadUpdateRequest(leadId, leadPhone, baggage);
  8236          var msg = UIModel.getInstance().leadUpdateRequest.formatJSON();
  8237          utils.setCallback(this, CALLBACK_TYPES.LEAD_UPDATE, callback);
  8238          utils.sendMessage(this, msg);
  8239      };
  8240  }
  8241  function initAgentLibraryChat (context) {
  8242      /**
  8243       * @namespace Chat
  8244       * @memberof AgentLibrary
  8245       */
  8246      'use strict';
  8247      var AgentLibrary = context.AgentLibrary;
  8248      /**
  8249       * Set the agent chat alias
  8250       * @memberof AgentLibrary.Chat
  8251       * @param {string} alias The alias string to be used for agent chat messages
  8252       */
  8253      AgentLibrary.prototype.setChatAlias = function(alias){
  8254          UIModel.getInstance().chatAliasRequest = new ChatAliasRequest(alias);
  8255          var msg = UIModel.getInstance().chatAliasRequest.formatJSON();
  8256          utils.sendMessage(this, msg);
  8257      };
  8258      /**
  8259       * Request to enter/exit a public chat room
  8260       * @memberof AgentLibrary.Chat
  8261       * @param {string} action "ENTER" | "EXIT"
  8262       * @param {integer} roomId Chat room id
  8263       */
  8264      AgentLibrary.prototype.publicChatRoom = function(action, roomId){
  8265          UIModel.getInstance().chatRoomRequest = new ChatRoomRequest(action, "PUBLIC", roomId);
  8266          var msg = UIModel.getInstance().chatRoomRequest.formatJSON();
  8267          utils.sendMessage(this, msg);
  8268      };
  8269      /**
  8270       * Request to enter/exit a private chat room
  8271       * @memberof AgentLibrary.Chat
  8272       * @param {string} action "ENTER" | "EXIT"
  8273       * @param {integer} roomId Chat room id
  8274       * @param {integer} agentOne Id for the logged in agent
  8275       * @param {integer} agentTwo Id for the agent or supervisor the logged in agent is chatting with
  8276       */
  8277      AgentLibrary.prototype.privateChatRoom = function(action, roomId, agentOne, agentTwo){
  8278          UIModel.getInstance().chatRoomRequest = new ChatRoomRequest(action, "PRIVATE", roomId, agentOne, agentTwo);
  8279          var msg = UIModel.getInstance().chatRoomRequest.formatJSON();
  8280          utils.sendMessage(this, msg);
  8281      };
  8282      /**
  8283       * Send a chat message to the given room
  8284       * @memberof AgentLibrary.Chat
  8285       * @param {integer} roomId Id for chat room
  8286       * @param {string} message The message to be sent
  8287       * @param {function} [callback=null] Callback function when chat message received
  8288       */
  8289      AgentLibrary.prototype.sendChat = function(roomId, message, callback){
  8290          UIModel.getInstance().chatSendRequest = new ChatSendRequest(roomId, message);
  8291          var msg = UIModel.getInstance().chatSendRequest.formatJSON();
  8292          utils.setCallback(this, CALLBACK_TYPES.CHAT, callback);
  8293          utils.sendMessage(this, msg);
  8294      };
  8295      /**
  8296       * Get list of supervisors for logged in agent
  8297       * @memberof AgentLibrary.Chat
  8298       * @param {function} [callback=null] Callback function when chat message received
  8299       */
  8300      AgentLibrary.prototype.getSupervisors = function(callback){
  8301          UIModel.getInstance().supervisorListRequest = new SupervisorListRequest();
  8302          var msg = UIModel.getInstance().supervisorListRequest.formatJSON();
  8303          utils.setCallback(this, CALLBACK_TYPES.SUPERVISOR_LIST, callback);
  8304          utils.sendMessage(this, msg);
  8305      };
  8306      /**
  8307       * Send accept/decline response when a chat is presented to an agent
  8308       * @memberof AgentLibrary.Chat
  8309       * @param {string} uii Unique identifier for the chat session
  8310       * @param {string} response ACCEPT|REJECT response
  8311       * @param {string} responseReason Agent reason for Reject
  8312       */
  8313      AgentLibrary.prototype.chatPresentedResponse = function(uii, messageId, response, responseReason){
  8314          UIModel.getInstance().chatPresentedRequest = new ChatPresentedResponseRequest(uii, messageId, response, responseReason);
  8315          var msg = UIModel.getInstance().chatPresentedRequest.formatJSON();
  8316          utils.sendMessage(this, msg);
  8317      };
  8318      /**
  8319       * Send an external chat message
  8320       * @memberof AgentLibrary.Chat
  8321       * @param {string} uii Unique identifier for the chat session
  8322       * @param {string} agentId The agent associated with the chat
  8323       * @param {string} message The message sent by the agent
  8324       */
  8325      AgentLibrary.prototype.chatMessage = function(uii, agentId, message){
  8326          UIModel.getInstance().chatMessageRequest = new ChatMessageRequest(uii, agentId, message, false);
  8327          var msg = UIModel.getInstance().chatMessageRequest.formatJSON();
  8328          utils.sendMessage(this, msg);
  8329      };
  8330      /**
  8331       * Send an whisper type chat message
  8332       * @memberof AgentLibrary.Chat
  8333       * @param {string} uii Unique identifier for the chat session
  8334       * @param {string} agentId The agent associated with the chat
  8335       * @param {string} message The message sent by the agent
  8336       */
  8337      AgentLibrary.prototype.chatWhisper = function(uii, agentId, message){
  8338          UIModel.getInstance().chatMessageRequest = new ChatMessageRequest(uii, agentId, message, true);
  8339          var msg = UIModel.getInstance().chatMessageRequest.formatJSON();
  8340          utils.sendMessage(this, msg);
  8341      };
  8342      /**
  8343       * Send a disposition to end a chat session
  8344       * @memberof AgentLibrary.Chat
  8345       * @param {string} uii Unique identifier for the chat session
  8346       * @param {number} agentId The agent's id
  8347       * @param {number} dispositionId Id of the selected disposition
  8348       * @param {string} [notes=""] Agent notes
  8349       * @param {boolean} sendAcknowlegement Whether or not to fire callback
  8350       * @param {object} [script=null] Script data associated with the chat session
  8351       */
  8352      AgentLibrary.prototype.chatDisposition = function(uii, agentId, dispositionId, notes, sendAcknowlegement, script, sessionId){
  8353          UIModel.getInstance().chatDispositionRequest = new ChatDispositionRequest(uii, agentId, dispositionId, notes, sendAcknowlegement, script, sessionId);
  8354          var msg = UIModel.getInstance().chatDispositionRequest.formatJSON();
  8355          utils.sendMessage(this, msg);
  8356      };
  8357      /**
  8358       * Send the chat to a different Chat Queue
  8359       * @memberof AgentLibrary.Chat
  8360       * @param {string} uii Unique identifier for the chat session
  8361       * @param {number} agentId The agent's id
  8362       * @param {number} chatQueueId Id of the Chat Queue to requeue to
  8363       * @param {number} skillId Skill id associated with the Chat Queue
  8364       * @param {boolean} [maintainAgent=fakse] Whether or not to keep the current agent connected to the chat on requeue
  8365       */
  8366      AgentLibrary.prototype.chatRequeue = function(uii, agentId, chatQueueId, skillId, maintainAgent){
  8367          UIModel.getInstance().chatRequeueRequest = new ChatRequeueRequest(uii, agentId, chatQueueId, skillId, maintainAgent);
  8368          var msg = UIModel.getInstance().chatRequeueRequest.formatJSON();
  8369          utils.sendMessage(this, msg);
  8370      };
  8371      /**
  8372       * Sent when agent starts/stops typing
  8373       * @memberof AgentLibrary.Chat
  8374       * @param {string} uii Unique identifier for the chat session
  8375       * @param {string} message Pending Agent message - sent to any monitoring Supervisors
  8376       */
  8377      AgentLibrary.prototype.chatTyping = function(uii,message){
  8378          UIModel.getInstance().chatTypingRequest = new ChatTypingRequest(uii,message);
  8379          var msg = UIModel.getInstance().chatTypingRequest.formatJSON();
  8380          utils.sendMessage(this, msg);
  8381      };
  8382      /**
  8383       * Request to add a session on an existing chat
  8384       * @memberof AgentLibrary.Chat
  8385       * @param {string} monitorAgentId Agent id handling this chat, the agent being monitored
  8386       */
  8387      AgentLibrary.prototype.monitorAgentChats = function(monitorAgentId){
  8388          UIModel.getInstance().monitorChatRequest = new MonitorChatRequest(monitorAgentId);
  8389          var msg = UIModel.getInstance().monitorChatRequest.formatJSON();
  8390          utils.sendMessage(this, msg);
  8391      };
  8392      /**
  8393       * Request to stop a chat monitoring session for a specific agent
  8394       * @memberof AgentLibrary.Chat
  8395       * @param {string} monitorAgentId Agent id of agent being monitored
  8396       */
  8397      AgentLibrary.prototype.stopMonitoringChatsByAgent = function(monitorAgentId){
  8398          UIModel.getInstance().stopMonitorChatRequest = new StopMonitorChatRequest(monitorAgentId);
  8399          var msg = UIModel.getInstance().stopMonitorChatRequest.formatJSON();
  8400          utils.sendMessage(this, msg);
  8401      };
  8402      /**
  8403       * Request to drop all chat monitoring sessions for the logged in agent
  8404       * @memberof AgentLibrary.Chat
  8405       */
  8406      AgentLibrary.prototype.stopMonitoringAllAgentChats = function(){
  8407          UIModel.getInstance().stopMonitorChatRequest = new StopMonitorChatRequest();
  8408          var msg = UIModel.getInstance().stopMonitorChatRequest.formatJSON();
  8409          utils.sendMessage(this, msg);
  8410      };
  8411      /**
  8412       * Request to terminate an active chat session
  8413       * @memberof AgentLibrary.Chat
  8414       * @param {string} uii Unique identifier for the chat session
  8415       * @param {string} agentId Current logged in agent id
  8416       * @param {string} sessionId Chat session id
  8417       */
  8418      AgentLibrary.prototype.leaveChat = function(uii, agentId, sessionId){
  8419          UIModel.getInstance().leaveChatRequest = new LeaveChatRequest(uii, agentId, sessionId);
  8420          var msg = UIModel.getInstance().leaveChatRequest.formatJSON();
  8421          utils.sendMessage(this, msg);
  8422      };
  8423      /**
  8424       * Request a list of active chats by agent id
  8425       * @memberof AgentLibrary.Chat
  8426       * @param {string} agentId Current logged in agent id
  8427       * @param {string} monitorAgentId Agent id handling chats
  8428       * @param {function} [callback=null] Callback function when chat-list request received
  8429       */
  8430      AgentLibrary.prototype.chatList = function(agentId, monitorAgentId, callback){
  8431          UIModel.getInstance().chatListRequest = new ChatListRequest(agentId, monitorAgentId);
  8432          var msg = UIModel.getInstance().chatListRequest.formatJSON();
  8433          utils.setCallback(this, CALLBACK_TYPES.CHAT_LIST, callback);
  8434          utils.sendMessage(this, msg);
  8435      };
  8436      /**
  8437       * set chat in state of agent-chat-end
  8438       * @memberof AgentLibrary.Chat
  8439       * @param {string} uii Unique identifier for the chat session
  8440       * @param {string} agentId Current logged in agent id
  8441       */
  8442      AgentLibrary.prototype.chatAgentEnd = function(agentId, uii){
  8443          UIModel.getInstance().chatAgentEnd = new ChatAgentEndRequest(agentId, uii);
  8444          var msg = UIModel.getInstance().chatAgentEnd.formatJSON();
  8445          utils.sendMessage(this, msg);
  8446      };
  8447      /**
  8448       * Sends chat state change message to IntelliQueue
  8449       * @memberof AgentLibrary.Agent
  8450       * @param {string} chatState The base chat state <br />
  8451       * CHAT-AVAILABLE | CHAT-PRESENTED | CHAT-ENGAGED | CHAT-RNA
  8452       * @param {function} [callback=null] Callback function when chatState response received
  8453       */
  8454      AgentLibrary.prototype.setChatState = function(chatState, callback){
  8455          UIModel.getInstance().chatStateRequest = new ChatStateRequest(chatState);
  8456          var msg = UIModel.getInstance().chatStateRequest.formatJSON();
  8457          utils.setCallback(this, CALLBACK_TYPES.CHAT_STATE, callback);
  8458          utils.sendMessage(this, msg);
  8459      };
  8460      /**
  8461       * initialize a chat session by sending a manual outbound sms
  8462       * @memberof AgentLibrary.Chat
  8463       * @param {string} agentId Current logged in agent id
  8464       * @param {number} chatQueueId Id of the Chat Queue to send this sms through
  8465       * @param {number} ani to receive the sms
  8466       * @param {number} dnis to be used for the sms
  8467       * @param {string} message content
  8468       */
  8469      AgentLibrary.prototype.sendManualOutboundSms = function(agentId, chatQueueId, ani, dnis, message){
  8470          UIModel.getInstance().chatManualSms = new ChatManualSmsRequest(agentId, chatQueueId, ani, dnis, message);
  8471          var msg = UIModel.getInstance().chatManualSms.formatJSON();
  8472          utils.sendMessage(this, msg);
  8473      };
  8474  }
  8475  function initAgentLibraryLogger(context) {
  8476      'use strict';
  8477      var AgentLibrary = context.AgentLibrary;
  8478      AgentLibrary.prototype.openLogger = function(){
  8479          var instance = this;
  8480          if("indexedDB" in context){
  8481              // Open database
  8482              var dbRequest = indexedDB.open("AgentLibraryLogging", 6); // version number
  8483              dbRequest.onerror = function(event) {
  8484                  console.error("Error requesting DB access");
  8485              };
  8486              dbRequest.onsuccess = function(event) {
  8487                  instance._db = event.target.result;
  8488                  //prune items older than 2 days
  8489                  instance.purgeLog(instance._db, "logger");
  8490                  instance._db.onerror = function(event) {
  8491                      // Generic error handler for all errors targeted at this database requests
  8492                      console.error("AgentLibrary: Database error - " + event.target.errorCode);
  8493                  };
  8494                  instance._db.onsuccess = function(event) {
  8495                      console.log("AgentLibrary: Successful logging of record");
  8496                  };
  8497              };
  8498              // This event is only implemented in recent browsers
  8499              dbRequest.onupgradeneeded = function(event) {
  8500                  instance._db = event.target.result;
  8501                  // Create an objectStore to hold log information. Key path should be unique
  8502                  if(!instance._db.objectStoreNames.contains("logger")){
  8503                      var objectStore = instance._db.createObjectStore("logger", { autoIncrement: true });
  8504                      // simple indicies: index name, index column path
  8505                      objectStore.createIndex("logLevel", "logLevel", {unique: false});
  8506                      objectStore.createIndex("dts", "dts", {unique: false});
  8507                      // index for logLevel and date range
  8508                      var name = "levelAndDate";
  8509                      var keyPath = ['logLevel','dts'];
  8510                      objectStore.createIndex(name, keyPath, {unique: false});
  8511                  }
  8512              };
  8513          }else{
  8514              console.warn("AgentLibrary: indexedDB NOT supported by your Browser.");
  8515          }
  8516      };
  8517      /**
  8518       * Purge records older than 2 days from the AgentLibrary log
  8519       * @memberof AgentLibrary
  8520       */
  8521      AgentLibrary.prototype.purgeLog = function(db, store){
  8522          var instance = this;
  8523          if(db){
  8524              try{
  8525                  var transaction = db.transaction([store], "readwrite");
  8526                  var objectStore = transaction.objectStore(store);
  8527                  var dateIndex = objectStore.index("dts");
  8528                  var endDate = new Date();
  8529                  endDate.setDate(endDate.getDate() - 2); // two days ago
  8530                  var range = IDBKeyRange.upperBound(endDate);
  8531                  dateIndex.openCursor(range).onsuccess = function(event){
  8532                      var cursor = event.target.result;
  8533                      if(cursor){
  8534                          objectStore.delete(cursor.primaryKey);
  8535                          cursor.continue();
  8536                      }
  8537                  };
  8538              } catch(err){
  8539                  // no op
  8540              }
  8541          }
  8542      };
  8543      /**
  8544       * Clear the AgentLibrary log by emptying the IndexedDB object store
  8545       * @memberof AgentLibrary
  8546       */
  8547      AgentLibrary.prototype.clearLog = function(db){
  8548          var transaction = db.transaction(["logger"], "readwrite");
  8549          var objectStore = transaction.objectStore("logger");
  8550          var objectStoreRequest = objectStore.clear();
  8551          objectStoreRequest.onsuccess = function(event){
  8552              console.log("AgentLibrary: logger database cleared");
  8553          };
  8554      };
  8555      AgentLibrary.prototype.deleteDB = function(dbName){
  8556          dbName = dbName || 'AgentLibraryLogging';
  8557          var DBDeleteRequest = indexedDB.deleteDatabase(dbName);
  8558           DBDeleteRequest.onerror = function(event) {
  8559           console.log("Error deleting database.", dbName);
  8560           };
  8561           DBDeleteRequest.onsuccess = function(event) {
  8562           console.log("Database", dbName, "deleted successfully");
  8563           };
  8564      };
  8565      AgentLibrary.prototype.getLogRecords = function(logLevel, startDate, endDate, maxRows, callback){
  8566          logLevel = logLevel || "";
  8567          var instance = this;
  8568          var transaction = instance._db.transaction(["logger"], "readonly");
  8569          var objStore = transaction.objectStore("logger");
  8570          var index = null,
  8571              cursor = null,
  8572              range = null,
  8573              limit = maxRows || 100;
  8574          utils.setCallback(instance, CALLBACK_TYPES.LOG_RESULTS, callback);
  8575          if(logLevel !== "" && logLevel.toUpperCase() !== "ALL" && logLevel.toUpperCase() !== "NO-STATS") { // looking for specific log level type
  8576              if(startDate && endDate){
  8577                  var lowerBound = [logLevel.toLowerCase(), startDate];
  8578                  var upperBound = [logLevel.toLowerCase(), endDate];
  8579                  range = IDBKeyRange.bound(lowerBound,upperBound);
  8580              }else if(startDate){
  8581                  range = IDBKeyRange.lowerBound([logLevel.toLowerCase(), startDate]);
  8582              }else if(endDate){
  8583                  range = IDBKeyRange.upperBound([logLevel.toLowerCase(), endDate]);
  8584              }
  8585              if(range !== null){
  8586                  // with the provided date range
  8587                  var levelAndDateReturn = [];
  8588                  var idxLevelAndDate = 0;
  8589                  index = objStore.index("levelAndDate");
  8590                  index.openCursor(range, "prev").onsuccess = function(event){
  8591                      cursor = event.target.result;
  8592                      if(cursor && idxLevelAndDate < limit){
  8593                          levelAndDateReturn.push(cursor.value);
  8594                          idxLevelAndDate = idxLevelAndDate + 1;
  8595                          cursor.continue();
  8596                      }else{
  8597                          utils.fireCallback(instance, CALLBACK_TYPES.LOG_RESULTS, levelAndDateReturn);
  8598                      }
  8599                  };
  8600              }else{
  8601                  // no date range specified, return all within log level
  8602                  var logLevelReturn = [];
  8603                  var idxLogLevel = 0;
  8604                  index = objStore.index("logLevel");
  8605                  index.openCursor(logLevel, "prev").onsuccess = function(event){
  8606                      cursor = event.target.result;
  8607                      if(cursor && idxLogLevel < limit){
  8608                          logLevelReturn.push(cursor.value);
  8609                          idxLogLevel = idxLogLevel + 1;
  8610                          cursor.continue();
  8611                      }else{
  8612                          utils.fireCallback(instance, CALLBACK_TYPES.LOG_RESULTS, logLevelReturn);
  8613                      }
  8614                  };
  8615              }
  8616          } else if(logLevel.toUpperCase() === "NO-STATS"){ // give us all types except stats
  8617              if(startDate && endDate){
  8618                  range = IDBKeyRange.bound(startDate,endDate);
  8619              }else if(startDate){
  8620                  range = IDBKeyRange.lowerBound(startDate);
  8621              }else if(endDate){
  8622                  range = IDBKeyRange.upperBound(endDate);
  8623              }
  8624              if(range !== null){
  8625                  // with the provided date range
  8626                  var dtsNoStatsReturn = [];
  8627                  var idxDTSNoStats = 0;
  8628                  index = objStore.index("dts");
  8629                  index.openCursor(range, "prev").onsuccess = function(event){
  8630                      cursor = event.target.result;
  8631                      if(cursor && idxDTSNoStats < limit){
  8632                          if(cursor.value.logLevel !== "stats"){
  8633                              dtsNoStatsReturn.push(cursor.value);
  8634                              idxDTSNoStats = idxDTSNoStats + 1;
  8635                          }
  8636                          cursor.continue();
  8637                      }else{
  8638                          utils.fireCallback(instance, CALLBACK_TYPES.LOG_RESULTS, dtsNoStatsReturn);
  8639                      }
  8640                  };
  8641              }else{
  8642                  // no date range specified, return all records
  8643                  var noStatsReturn = [];
  8644                  var idxNoStats = 0;
  8645                  objStore.openCursor().onsuccess = function(event){
  8646                      cursor = event.target.result;
  8647                      if(cursor && idxNoStats < limit){
  8648                          if(cursor.value.logLevel !== "stats"){
  8649                              noStatsReturn.push(cursor.value);
  8650                              idxNoStats = idxNoStats + 1;
  8651                          }
  8652                          cursor.continue();
  8653                      }else{
  8654                          utils.fireCallback(instance, CALLBACK_TYPES.LOG_RESULTS, noStatsReturn);
  8655                      }
  8656                  };
  8657              }
  8658          } else { // give us all log level types
  8659              if(startDate && endDate){
  8660                  range = IDBKeyRange.bound(startDate,endDate);
  8661              }else if(startDate){
  8662                  range = IDBKeyRange.lowerBound(startDate);
  8663              }else if(endDate){
  8664                  range = IDBKeyRange.upperBound(endDate);
  8665              }
  8666              if(range !== null){
  8667                  // with the provided date range
  8668                  var dtsReturn = [];
  8669                  var idxDTS = 0;
  8670                  index = objStore.index("dts");
  8671                  index.openCursor(range, "prev").onsuccess = function(event){
  8672                      cursor = event.target.result;
  8673                      if(cursor && idxDTS < limit){
  8674                          dtsReturn.push(cursor.value);
  8675                          idxDTS = idxDTS + 1;
  8676                          cursor.continue();
  8677                      }else{
  8678                          utils.fireCallback(instance, CALLBACK_TYPES.LOG_RESULTS, dtsReturn);
  8679                      }
  8680                  };
  8681              }else{
  8682                  // no date range specified, return all records
  8683                  var allValsReturn = [];
  8684                  var idxAll = 0;
  8685                  objStore.openCursor().onsuccess = function(event){
  8686                      cursor = event.target.result;
  8687                      if(cursor && idxAll < limit){
  8688                          allValsReturn.push(cursor.value);
  8689                          idxAll = idxAll + 1;
  8690                          cursor.continue();
  8691                      }else{
  8692                          utils.fireCallback(instance, CALLBACK_TYPES.LOG_RESULTS, allValsReturn);
  8693                      }
  8694                  };
  8695              }
  8696          }
  8697          return null;
  8698      };
  8699  }
  8700  function initAgentLibraryConsoleLogger(context) {
  8701      'use strict';
  8702      var AgentLibrary = context.AgentLibrary;
  8703      AgentLibrary.prototype.openConsoleLogger = function() {
  8704          var instance = this;
  8705          if("indexedDB" in context){
  8706              var dbRequest = indexedDB.open("AgentLibraryConsoleLogging", 1);
  8707              dbRequest.onerror = function(event){
  8708                  console.error("Error requesting DB access");
  8709              };
  8710              dbRequest.onsuccess = function(event){
  8711                  instance._consoleDb = event.target.result;
  8712                  //prune items older than 2 days
  8713                  instance.purgeLog(instance._consoleDb, "consoleLogger");
  8714                  instance._consoleDb.onerror = function(event) {
  8715                      // Generic error handler for all errors targeted at this database requests
  8716                      console.error("AgentLibrary: Database error - " + event.target.errorCode);
  8717                  };
  8718                  instance._consoleDb.onsuccess = function(event) {
  8719                      console.log("AgentLibrary: Successful logging of record");
  8720                  };
  8721                  _overrideConsole();
  8722              };
  8723              // This event is only implemented in recent browsers
  8724              dbRequest.onupgradeneeded = function(event) {
  8725                  instance._consoleDb = event.target.result;
  8726                  // Create an objectStore to hold log information. Key path should be unique
  8727                  if(!instance._consoleDb.objectStoreNames.contains("consoleLogger")){
  8728                      var objectStore = instance._consoleDb.createObjectStore("consoleLogger", { autoIncrement: true });
  8729                      // simple indicies: index name, index column path
  8730                      objectStore.createIndex("type", "type", {unique: false});
  8731                      objectStore.createIndex("dts", "dts", {unique: false});
  8732                      objectStore.createIndex("agentId", "agentId", {unique: false});
  8733                      // index for type and agent id
  8734                      var name = "typeAndAgent";
  8735                      var keyPath = ['type', 'agentId'];
  8736                      objectStore.createIndex(name, keyPath, {unique: false});
  8737                  }
  8738                  _overrideConsole();
  8739              };
  8740          } else {
  8741              console.warn("AgentLibrary: indexedDB NOT supported by your Browser.");
  8742          }
  8743      };
  8744      AgentLibrary.prototype.getConsoleLogRecords = function(type, callback) {
  8745          var agentId = UIModel.getInstance().agentSettings.agentId;   // only return records for this agent id
  8746          var instance = this;
  8747          var transaction = instance._consoleDb.transaction(["consoleLogger"], "readonly");
  8748          var objStore = transaction.objectStore("consoleLogger");
  8749          var index = null,
  8750              cursor = null,
  8751              range = null,
  8752              limit = 5000;
  8753          utils.setCallback(instance, CALLBACK_TYPES.LOG_CONSOLE_RESULTS, callback);
  8754          var result = [];
  8755          if(type) {
  8756              // everything with this type
  8757              index = objStore.index("typeAndAgent");
  8758              range = IDBKeyRange.only([type.toUpperCase(), agentId]);
  8759          } else {
  8760              index = objStore.index("agentId");
  8761              range = IDBKeyRange.only(agentId);
  8762          }
  8763          var count = 0;
  8764          index.openCursor(range, "prev").onsuccess = function(event){
  8765              cursor = event.target.result;
  8766              if(cursor && count < limit) {
  8767                  result.push(cursor.value);
  8768                  count++;
  8769                  cursor.continue();
  8770              } else {
  8771                  utils.fireCallback(instance, CALLBACK_TYPES.LOG_CONSOLE_RESULTS, result);
  8772              }
  8773          };
  8774      };
  8775      function _overrideConsole() {
  8776          // override the window.console functions, process as normal then save to the local db
  8777          var browserConsole = Object.assign({}, window.console);
  8778          (function (defaultConsole) {
  8779              var instance = UIModel.getInstance().libraryInstance;
  8780              var agentSettings = UIModel.getInstance().agentSettings;
  8781              function _getRecord(type, text) {
  8782                  if(typeof text === 'function') {
  8783                      text = text.toString();
  8784                  } else if(typeof text === 'object') {
  8785                      try {
  8786                          text = JSON.stringify(text);
  8787                      } catch(e) {}
  8788                  }
  8789                  return {
  8790                      type: type,
  8791                      message: text,
  8792                      dts: new Date(),
  8793                      agentId: agentSettings.agentId,
  8794                      agentName: agentSettings.firstName + ' ' + agentSettings.lastName
  8795                  };
  8796              }
  8797              function _saveRecord(type, text) {
  8798                  if (instance._consoleDb) {
  8799                      var transaction = instance._consoleDb.transaction(["consoleLogger"], "readwrite");
  8800                      var store = transaction.objectStore("consoleLogger");
  8801                      store.add(_getRecord(type, text));
  8802                  }
  8803              }
  8804              window.console.log = function(text) {
  8805                  defaultConsole.log(text);
  8806                  _saveRecord('LOG', text);
  8807              };
  8808              window.console.info = function(text) {
  8809                  defaultConsole.info(text);
  8810                  _saveRecord('INFO', text);
  8811              };
  8812              window.console.warn = function(text) {
  8813                  defaultConsole.warn(text);
  8814                  _saveRecord('WARN', text);
  8815              };
  8816              window.console.error = function(text) {
  8817                  defaultConsole.error(text);
  8818                  _saveRecord('ERROR', text);
  8819              };
  8820          }(browserConsole));
  8821      }
  8822  }
  8823  var initAgentLibrary = function (context) {
  8824      initAgentLibraryCore(context);
  8825      initAgentLibrarySocket(context);
  8826      initAgentLibraryAgent(context);
  8827      initAgentLibraryCall(context);
  8828      initAgentLibraryLead(context);
  8829      initAgentLibraryChat(context);
  8830      initAgentLibraryLogger(context);
  8831      initAgentLibraryConsoleLogger(context);
  8832      return context.AgentLibrary;
  8833  };
  8834  if (typeof define === 'function' && define.amd) {
  8835      // Expose Library as an AMD module if it's loaded with RequireJS or
  8836      // similar.
  8837      //console.log("AgentLibrary: using AMD");
  8838      define(function () {
  8839          return initAgentLibrary({});
  8840      });
  8841  } else if (typeof module === 'object' && module.exports) {
  8842      // Node. Does not work with strict CommonJS, but
  8843      // only CommonJS-like environments that support module.exports,
  8844      // like Node.
  8845      //console.log("AgentLibrary: Using Node");
  8846      module.exports = initAgentLibrary(this);
  8847  } else {
  8848      // Load Library normally (creating a Library global) if not using an AMD
  8849      // loader.
  8850      //console.log("AgentLibrary: Not using AMD");
  8851      initAgentLibrary(this);
  8852  }
  8853  } (this));