/*
   * Utility function to add the JSON description of a active
   * trigger to JSON array.
   */
  private static void addTriggerInfoToArray(Context context, Cursor trig, JSONArray jArray) {
    String rtDesc = trig.getString(trig.getColumnIndexOrThrow(TriggerDB.KEY_RUNTIME_DESCRIPT));
    TriggerRunTimeDesc desc = new TriggerRunTimeDesc();
    desc.loadString(rtDesc);

    String notifDesc = trig.getString(trig.getColumnIndexOrThrow(TriggerDB.KEY_NOTIF_DESCRIPT));

    String trigDesc = trig.getString(trig.getColumnIndexOrThrow(TriggerDB.KEY_TRIG_DESCRIPT));

    String trigType = trig.getString(trig.getColumnIndexOrThrow(TriggerDB.KEY_TRIG_TYPE));

    String campaignUrn = trig.getString(trig.getColumnIndexOrThrow(TriggerDB.KEY_CAMPAIGN_URN));

    JSONObject jPref = new JSONObject();
    TriggerBase trigBase = new TriggerTypeMap().getTrigger(trigType);
    if (trigBase != null) {
      jPref = trigBase.getPreferences(context);
    }

    JSONObject jTrigInfo = new JSONObject();

    try {
      jTrigInfo.put(KEY_TRIGGER_TYPE, trigType);
      jTrigInfo.put(KEY_TRIGGER_DESC, new JSONObject(trigDesc));
      jTrigInfo.put(KEY_NOTIF_DESC, new JSONObject(notifDesc));
      jTrigInfo.put(KEY_RUNTIME_DESC, new JSONObject(desc.toHumanReadableString()));
      jTrigInfo.put(KEY_TRIGER_PREF, jPref);
      jTrigInfo.put(KEY_CAMPAIGN_URN, campaignUrn);
    } catch (JSONException e) {
      return;
    }

    jArray.put(jTrigInfo);
  }
  /*
   * Helper function to prepare the list of active surveys corresponding
   * to trigger.
   *
   * A trigger is active if it has not expired (the notification duration
   * has not been reached) after going off the last time.
   *
   * All surveys associated with an active active trigger are active
   * 	- EXCEPT those which have already been taken by the user within
   * 	  the suppression window.
   */
  private static HashSet<String> getActiveSurveys(Context context, Cursor trig) {

    HashSet<String> actSurveys = new HashSet<String>();

    String runTime = trig.getString(trig.getColumnIndexOrThrow(TriggerDB.KEY_RUNTIME_DESCRIPT));

    String notif = trig.getString(trig.getColumnIndexOrThrow(TriggerDB.KEY_NOTIF_DESCRIPT));

    String actions = trig.getString(trig.getColumnIndexOrThrow(TriggerDB.KEY_TRIG_ACTION_DESCRIPT));

    String campaignUrn = trig.getString(trig.getColumnIndexOrThrow(TriggerDB.KEY_CAMPAIGN_URN));

    Log.i(DEBUG_TAG, "NotifSurveyAdaptor: Calculating active surveys for trigger");

    TriggerRunTimeDesc rtDesc = new TriggerRunTimeDesc();
    NotifDesc notifDesc = new NotifDesc();
    TriggerActionDesc actDesc = new TriggerActionDesc();

    if (!rtDesc.loadString(runTime)
        || !notifDesc.loadString(notif)
        || !actDesc.loadString(actions)) {

      Log.w(DEBUG_TAG, "NotifSurveyAdaptor: Descritptor(s) failed to parse");

      return actSurveys;
    }

    if (!rtDesc.hasTriggerTimeStamp()) {
      Log.i(DEBUG_TAG, "NotifSurveyAdaptor: Trigger time stamp is invalid");

      return actSurveys;
    }

    long now = System.currentTimeMillis();
    long trigTS = rtDesc.getTriggerTimeStamp();

    if (trigTS > now) {
      Log.w(DEBUG_TAG, "NotifSurveyAdaptor: Trigger time stamp is in the future!");
      return actSurveys;
    }

    // How long it has been since the trigger went off
    long elapsedMS = now - trigTS;

    long durationMS = notifDesc.getDuration() * 60000;
    long suppressMS = notifDesc.getSuppression() * 60000;

    if (elapsedMS < durationMS) {

      // The trigger has not expired, check each survey

      String[] surveys = actDesc.getSurveys();
      for (int i = 0; i < surveys.length; i++) {

        // Has the survey been taken in within the
        // suppression window?
        if (IsSurveyTaken(context, campaignUrn, surveys[i], trigTS - suppressMS)) {
          continue;
        }

        // Add the active survey to the set
        actSurveys.add(surveys[i]);
      }
    }

    return actSurveys;
  }
  /*
   * To be called when a trigger expires. This function logs using
   * SystemLog, the list of all surveys not taken by the user
   * but were activated by the given trigger.
   */
  public static void handleExpiredTrigger(Context context, int trigId) {
    TriggerDB db = new TriggerDB(context);
    db.open();

    String sActDesc = db.getActionDescription(trigId);
    String sTrigDesc = db.getTriggerDescription(trigId);
    String sTrigType = db.getTriggerType(trigId);
    String sRTDesc = db.getRunTimeDescription(trigId);
    String sCampaignUrn = db.getCampaignUrn(trigId);

    db.close();

    if (sActDesc == null
        || sTrigDesc == null
        || sTrigType == null
        || sCampaignUrn == null
        || sRTDesc == null) {

      return;
    }

    TriggerActionDesc actDesc = new TriggerActionDesc();
    if (!actDesc.loadString(sActDesc)) {
      return;
    }

    TriggerRunTimeDesc rtDesc = new TriggerRunTimeDesc();
    if (!rtDesc.loadString(sRTDesc)) {
      return;
    }

    LinkedList<String> untakenList = new LinkedList<String>();
    for (String survey : actDesc.getSurveys()) {

      if (!IsSurveyTaken(context, sCampaignUrn, survey, rtDesc.getTriggerTimeStamp())) {

        untakenList.add(survey);
      }
    }

    if (untakenList.size() == 0) {
      return;
    }

    JSONArray jSurveyList = new JSONArray();
    for (String survey : actDesc.getSurveys()) {
      jSurveyList.put(survey);
    }

    JSONArray jUntakenSurveys = new JSONArray();
    for (String unTakenSurvey : untakenList) {
      jUntakenSurveys.put(unTakenSurvey);
    }

    JSONObject jExpired = new JSONObject();

    try {
      jExpired.put(KEY_TRIGGER_TYPE, sTrigType);
      jExpired.put(KEY_TRIGGER_DESC, new JSONObject(sTrigDesc));
      jExpired.put(KEY_SURVEY_LIST, jSurveyList);
      jExpired.put(KEY_UNTAKEN_SURVEYS, jUntakenSurveys);
      jExpired.put(KEY_CAMPAIGN_URN, sCampaignUrn);
    } catch (JSONException e) {
      return;
    }

    // Log the info
    String msg = "Expired trigger has surveys not taken: " + jExpired.toString();

    Log.i(DEBUG_TAG, "NotifSurveyAdaptor: SystemLogging the following message: ");
    Log.i(DEBUG_TAG, msg);

    systemLog(context, msg);
  }