importPackage(java.lang);
importPackage(java.util);
importPackage(java.io);
importPackage(java.net);
importPackage(java.sql);
importPackage(java.text);
importClass(Packages.com.alarmpoint.integrationagent.apxml.APXMLMessage);
importClass(Packages.com.alarmpoint.integrationagent.apxml.APXMLToken);
importClass(Packages.com.thoughtworks.xstream.XStream);
importClass(Packages.com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider);

var xstream = new XStream(new PureJavaReflectionProvider());
XStream.setupDefaultSecurity(xstream);
xstream.allowTypesByWildcard(["com.alarmpoint.**", "java.util.*"]);

/**
 * This is the main method for handling APXML messages sent to the
 * Integration Service by APClient.
 */
function apia_input(apxml)
{
  // Return null because this sample integration is not expected to send or receive messages in this manner.
  return null;
}

/**
 * This is the main method for handling APXML messages sent to the
 * Integration Service by xMatters.  The messages may be responses to
 * previous submissions, or they may be requests to the Integration Service
 * that originate from xMatters
 * (e.g., via an ExternalServiceMessage/ExternalServiceRequest2).
 * <p>
 * Any APXMLMessage object that this method returns will be sent to xMatters
 * either via the Integration Service's outbound queues or directly as a
 * Web Service response, depending on the mechanism used to submit the APXML.
 */
function apia_response(apxml)
{
  var method = apxml.getMethod();
  if (APXMLMessage.OK_METHOD.equalsIgnoreCase(method))
  {
    return handleOK(apxml);
  }
  else if (APXMLMessage.ERROR_METHOD.equalsIgnoreCase(method))
  {
    return handleERROR(apxml);
  }
  else if (APXMLMessage.SEND_METHOD.equalsIgnoreCase(method))
  {
    return handleSend(apxml);
  }
  else if (APXMLMessage.REQUEST_METHOD.equalsIgnoreCase(method))
  {
    return handleRequest(apxml);
  }
  else
  {
    throw new IllegalArgumentException("Unrecognized APXML method: " + method);
  }
}


/**
 * OK responses are returned by xMatters for each APXML message that it accepts
 * from an Integration Service.
 * <p>
 * This implementation just logs the ack.
 */
function handleOK(apxml)
{
  var id = apxml.getTransactionId();
  ServiceAPI.getLogger().info("Submission of transaction " + id + " succeeded.");
}


/**
 * ERROR responses are returned by xMatters for each APXML message that it
 * is unable to accept from an Integration Service.
 * <p>
 * This implementation just logs the error.
 */
function handleERROR(apxml)
{
  var transaction = apxml.getTransactionId();
  var code = apxml.getValue(APXMLMessage.ERROR_CODE);
  ServiceAPI.getLogger().error("Submission of transaction " + transaction + " failed with error code " + code);
}


/**
 * This implementation just logs the request, there shouldn't be any direct calls to this method
 */
function handleRequest(apxml)
{
  ServiceAPI.getLogger().error("Service received unexpected 'Request' with message: " + apxml);
}

/**
 * The main routine for handling Requests starts here.
 * <p>
 * Throw an exception that will be logged by the Integration Agent.
 */
function handleSend(apxml)
{
  /*************************************************************************************************************/
  // This is the function that will handle successful queries from the Integrated Properties section on the form.
  // Any returned APXMLMessage object will be sent as the response from the IA to the form.

  // This value will always be sent as part of the request. You can use this value to dispatch the request
  // to one of several functions in this file.
  /*************************************************************************************************************/
  var action = apxml.getValue("xmattersRebRequestAction");

  // For this sample, we are providing the user with getIncident to call and fetch integrated properties.
  if (action == "getIncident") {

    return handleGetIncident(apxml);

  } else {
    ServiceAPI.getLogger().error("Unknown or unspecified xmattersRebRequestAction: " + action);
    return;
  }
}

function handleGetIncident(apxml) {

  // All responses must include this value from the request so that the response can be matched to its
  // originating request.
  var requestUuid = apxml.getValue("xmattersRebRequestUuid");


  // The getEventProperties helper method will read the request properties out of the request.
  var obj = getEventProperties(apxml);

  // Construct a string representation of the properties that we can output to the log file
  var requestProperties = '';
  for (var propName in obj) {
	  requestProperties += "\t" + propName + ": " + obj[propName] + "\n";
  }

  ServiceAPI.getLogger().warn("Received request [UUID " + requestUuid + "] with properties: \n" + requestProperties);

  // Create a minimal response
  var response = ServiceAPI.createAPXML();
  response.setMethod(APXMLMessage.RESPONSE_METHOD);
  response.setSubclass(APXMLMessage.RESPONSE_SUBCLASS);

  if (apxml.hasToken(APXMLMessage.APIA_PRIORITY)) {
    response.setToken(APXMLMessage.APIA_PRIORITY, apxml.getValue(APXMLMessage.APIA_PRIORITY));
  } else {
    response.setToken(APXMLMessage.APIA_PRIORITY, APXMLMessage.APIA_PRIORITY_HIGH);
  }

  /*************************************************************************************************************/
  // This field is REQUIRED in the response. If omitted, xMatters will not be able to match the response to the
  // request that originated it.
  /*************************************************************************************************************/
  response.setToken('xmattersRebRequestUuid', requestUuid, APXMLToken.Type.STRING);

  // Here we query an external data source for the values of the integrated properties
  var incidentJson = getIncident(obj['incidentId']);
  var incident = JSON.parse(incidentJson);

  // Here we add some sample properties to the response.  These will be used to populate the response properties
  // on the form, assuming properties with these names have been defined.
  var addTokens = {};
  addTokens['Incident Type'] = incident.incident.type;
  addTokens['Summary'] = incident.incident.summary;
  addTokens['Status'] = incident.incident.status;
  addTokens['Is Important'] = incident.incident.important;
  addTokens['Assignee'] = incident.incident.assignee;

  /*************************************************************************************************************/
  // Add the response properties to the response message. The field MUST be called "additionalTokens", and the
  // expected value should be a JSON representation of the values. Use JSON.stringify() to encode the values as
  // JSON.
  /*************************************************************************************************************/
  response.setToken('additionalTokens', JSON.stringify(addTokens), APXMLToken.Type.STRING);

  ServiceAPI.getLogger().warn('Sending response with tokens ' + JSON.stringify(addTokens));

  // Return the response so that it gets sent back to xMatters.
  return response;
}

/**
 * The request properties are passed as "additionalTokens" in the request.  They appear as XML, so they must
 * be converted to a JavaScript object.
 */
function getEventProperties(apxml) {

  var evProps = apxml.getValue("additionalTokens");

  // deserialize the additional tokens from the XML
  if (evProps != null && evProps != "") {
    var addTokensLinkedHashMap = xstream.fromXML(evProps);
  } else {
    var addTokensLinkedHashMap = new HashMap();
  }

  // Construct a JavaScript object with the key/values defined in the XML.
  var obj = {};
  var keyIterator = addTokensLinkedHashMap.keySet().iterator();
  while (keyIterator.hasNext()) {
    key = keyIterator.next();
    obj[key] = addTokensLinkedHashMap.get(key);
  }

  return obj;
}

/**
 * Sample function to "look up" an incident by ID.
 */
function getIncident(incidentId) {
  switch (parseInt(incidentId)) {
  case 1:
    return '{"incident":{"summary":"Mail server down","type":"System down","status":"Active","important":true,"assignee":"Mike"}}';
  case 2:
    return '{"incident":{"summary":"High latency between Virginia and DC","type":"Network","status":"Suspended","important":true,"assignee":"Mike"}}';
  case 3:
    return '{"incident":{"summary":"App server van-26 failed to restart","type":"System down","status":"Stopped","important":true,"assignee":"Jenny"}}';
  case 4:
    return '{"incident":{"summary":"Database backups failed Jan. 18","type":"Maintenance failure","status":"Active","important":false,"assignee":"Sean"}}';
  case 5:
    return '{"incident":{"summary":"Recurrent Java OOM conditions on app server tor-38","type":"System error","status":"Stopped","important":false,"assignee":"Adrian"}}';
  case 6:
    return '{"incident":{"summary":"SSL certificate expired for dev subdomain","type":"Configuration error","status":"Suspended","important":true,"assignee":"Amr"}}';
  case 7:
    return '{"incident":{"summary":"Intermittent APN delivery failures and delays","type":"System error","status":"Active","important":true,"assignee":"Amr"}}';
  case 8:
    return '{"incident":{"summary":"Repeated health monitor notifications about time drift on database server","type":"Maintenance failure","status":"BadStatus","important":BadBoolean,"assignee":"BadUser"}}';
  default:
    return '{"incident":{"summary":"No incident matched ID ' + incidentId + '","type":"No incident matched ID ' + incidentId + '","status":"Stopped","important":false,"assignee":"Sean"}}';
  }
}

/*
 * Method to handle all accept responses from xMatters.
 *
 * This method will only be called when the token provideServiceMessages is set to TRUE.
 */
function handleAccept(messageText, incidentId, assignee)
{

}
/*
 * Method to handle all reject responses from xMatters.
 *
 * This method will only be called when the token provideServiceMessages is set to TRUE.
 */
function handleReject(messageText, incidentId, assignee)
{

}
/*
 * Method to handle all annotations from xMatters.
 *
 * This method will only be called when the token provideServiceMessages is set to TRUE.
 */
function handleAnnotate(messageText, incidentId, assignee)
{

}
