content: /* 
   * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 
   * 
   * Licensed under the Apache License, Version 2.0 (the "License"); 
   * you may not use this file except in compliance with the License. 
   * You may obtain a copy of the License at 
   * 
   * http://www.apache.org/licenses/LICENSE-2.0 
   * 
   * Unless required by applicable law or agreed to in writing, software 
   * distributed under the License is distributed on an "AS IS" BASIS, 
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
   * See the License for the specific language governing permissions and 
   * limitations under the License. 
   */
  
  package com.amazon.cordova.plugin;
  
  import org.apache.cordova.CordovaActivity;
  import org.json.JSONObject;
  import android.app.Notification;
  import android.app.NotificationManager;
  import android.app.PendingIntent;
  import android.content.Context;
  import android.content.Intent;
  import android.content.SharedPreferences;
  import android.os.Bundle;
  import android.text.Html;
  import android.text.TextUtils;
  import android.util.Log;
  import android.app.Notification.Builder;
  
  import com.amazon.device.messaging.ADMMessageHandlerBase;
  import com.amazon.device.messaging.ADMMessageReceiver;
  
  /**
   * The ADMMessageHandler class receives messages sent by ADM via the receiver.
   */
  
  public class ADMMessageHandler extends ADMMessageHandlerBase {
  
      private static final String ERROR_EVENT = "error";
      public static final String PUSH_BUNDLE = "pushBundle";
      public static final String ERROR_MSG = "msg";
      private static final String SHOW_MESSAGE_PREF = "showmessageinnotification";
      private static final String DEFAULT_MESSAGE_PREF = "defaultnotificationmessage";
      private static boolean shouldShowOfflineMessage = false;
      private static String defaultOfflineMessage = null;
      private static final String PREFS_NAME = "PushPluginPrefs";
      private static final String DEFAULT_MESSAGE_TEXT = "You have a new message.";
      
      // An identifier for ADM notification unique within your application
      // It allows you to update the same notification later on
      public static final int NOTIFICATION_ID = 519;
      static Intent notificationIntent = null;
  
      /**
       * Class constructor.
       */
      public ADMMessageHandler() {
          super(ADMMessageHandler.class.getName());
      }
  
      /**
       * Class constructor, including the className argument.
       * 
       * @param className
       *            The name of the class.
       */
      public ADMMessageHandler(final String className) {
          super(className);
      }
  
      /**
       * The Receiver class listens for messages from ADM and forwards them to the ADMMessageHandler class.
       */
      public static class Receiver extends ADMMessageReceiver {
          public Receiver() {
              super(ADMMessageHandler.class);
  
          }
  
          // Nothing else is required here; your broadcast receiver automatically
          // forwards intents to your service for processing.
      }
  
      /** {@inheritDoc} */
      @Override
      protected void onRegistered(final String newRegistrationId) {
          // You start the registration process by calling startRegister() in your Main Activity. 
          // When the registration ID is ready, ADM calls onRegistered()
          // on your app. Transmit the passed-in registration ID to your server, so
          // your server can send messages to this app instance. onRegistered() is also
          // called if your registration ID is rotated or changed for any reason;
          // your app should pass the new registration ID to your server if this occurs.
  
          // we fire the register event in the web app, register handler should
          // fire to send the registration ID to your server via a header key/value pair over HTTP.(AJAX)
          PushPlugin.sendRegistrationIdWithEvent(PushPlugin.REGISTER_EVENT,
              newRegistrationId);
      }
  
      /** {@inheritDoc} */
      @Override
      protected void onUnregistered(final String registrationId) {
          // If your app is unregistered on this device, inform your server that
          // this app instance is no longer a valid target for messages.
          PushPlugin.sendRegistrationIdWithEvent(PushPlugin.UNREGISTER_EVENT,
              registrationId);
      }
  
      /** {@inheritDoc} */
      @Override
      protected void onRegistrationError(final String errorId) {
          // You should consider a registration error fatal. In response, your app
          // may degrade gracefully, or you may wish to notify the user that this part
          // of your app's functionality is not available.
          try {
              JSONObject json;
              json = new JSONObject().put(PushPlugin.EVENT, ERROR_EVENT);
              json.put(ADMMessageHandler.ERROR_MSG, errorId);
  
              PushPlugin.sendJavascript(json);
          } catch (Exception e) {
              Log.getStackTraceString(e);
          }
      }
  
      /** {@inheritDoc} */
      @Override
      protected void onMessage(final Intent intent) {
          // Extract the message content from the set of extras attached to
          // the com.amazon.device.messaging.intent.RECEIVE intent.
  
          // Extract the payload from the message
          Bundle extras = intent.getExtras();
          if (extras != null && (extras.getString(PushPlugin.MESSAGE) != null)) {
              // if we are in the foreground, just surface the payload, else post
              // it to the statusbar
              if (PushPlugin.isInForeground()) {
                  extras.putBoolean(PushPlugin.FOREGROUND, true);
                  PushPlugin.sendExtras(extras);
              } else {
                  extras.putBoolean(PushPlugin.FOREGROUND, false);
                  createNotification(this, extras);
              }
          }
      }
  
      /**
       * Creates a notification when app is not running or is not in foreground. It puts the message info into the Intent
       * extra
       * 
       * @param context
       * @param extras
       */
      public void createNotification(Context context, Bundle extras) {
          NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
          String appName = getAppName(this);
  
          // reuse the intent so that we can combine multiple messages into extra
          if (notificationIntent == null) {
              notificationIntent = new Intent(this, ADMHandlerActivity.class);
          }
          notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP
              | Intent.FLAG_ACTIVITY_CLEAR_TOP);
          notificationIntent.putExtra("pushBundle", extras);
  
          PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
              notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
  
          final Builder notificationBuilder = new Notification.Builder(context);
          notificationBuilder.setSmallIcon(context.getApplicationInfo().icon)
              .setWhen(System.currentTimeMillis())
              .setContentIntent(contentIntent);
  
          if (this.shouldShowMessageInNotification()) {
              String message = extras.getString(PushPlugin.MESSAGE);
              notificationBuilder.setContentText(Html.fromHtml(message).toString());
          } else {
              notificationBuilder.setContentText(this.defaultMessageTextInNotification());
          }
  
          String title = appName;
          notificationBuilder.setContentTitle(title).setTicker(title);
          notificationBuilder.setAutoCancel(true);
          // Because the ID remains unchanged, the existing notification is updated.
          notificationManager.notify((String) appName, NOTIFICATION_ID,
              notificationBuilder.getNotification());
      }
  
      public static void cancelNotification(Context context) {
          NotificationManager mNotificationManager = (NotificationManager) context
              .getSystemService(Context.NOTIFICATION_SERVICE);
          mNotificationManager.cancel((String) getAppName(context),
              NOTIFICATION_ID);
      }
  
      private static String getAppName(Context context) {
          CharSequence appName = context.getPackageManager().getApplicationLabel(
              context.getApplicationInfo());
          return (String) appName;
      }
  
      // clean up the message in the intent
      static void cleanupNotificationIntent() {
          if (notificationIntent != null) {
              Bundle pushBundle = notificationIntent.getExtras().getBundle(
                  PUSH_BUNDLE);
              if (pushBundle != null) {
                  pushBundle.clear();
              }
  
          }
      }
  
      public static Bundle getOfflineMessage() {
          Bundle pushBundle = null;
          if (notificationIntent != null) {
              pushBundle = notificationIntent.getExtras().getBundle(PUSH_BUNDLE);
              if (pushBundle.isEmpty()) {
                  pushBundle = null;
              }
          }
          return pushBundle;
      }
  
      /**
       * Reads "shownotificationmessage" & "defaultnotificationmessage" config options
       * If this is first-time it saves them to sharedPreferences so they can be read
       * when app is forced-stop or killed
       */
      public static void saveConfigOptions(Context context) {
          if (context != null && TextUtils.isEmpty(defaultOfflineMessage)) {
              // read config options from config.xml
              shouldShowOfflineMessage = ((CordovaActivity) context)
                  .getBooleanProperty(SHOW_MESSAGE_PREF, false);
              defaultOfflineMessage = ((CordovaActivity) context)
                  .getStringProperty(DEFAULT_MESSAGE_PREF, null);
  
              // save them to sharedPreferences if necessary
              SharedPreferences config = context.getApplicationContext().getSharedPreferences(PREFS_NAME, 0);
              SharedPreferences.Editor editor = config.edit();
              editor.putBoolean(SHOW_MESSAGE_PREF, shouldShowOfflineMessage);
              editor.putString(DEFAULT_MESSAGE_PREF, defaultOfflineMessage);
              // save prefs to disk
              editor.commit();
          }
  
      }
      
      /**
       * Gets "shownotificationmessage" config option
       * 
       * @return returns boolean- true is shownotificationmessage is set to true in config.xml/sharedPreferences otherwise false
       */
      private boolean shouldShowMessageInNotification() {
          //check if have cached copy of this option
          if (TextUtils.isEmpty(defaultOfflineMessage)) {
              //need to read it from sharedPreferences
              SharedPreferences config = this.getApplicationContext().getSharedPreferences(PREFS_NAME,0);
              if (config != null) {
                  shouldShowOfflineMessage = config.getBoolean(SHOW_MESSAGE_PREF, true);
              }
          }
          return shouldShowOfflineMessage;
      }
      
      /**
       * Gets "defaultnotificationmessage" config option
       * 
       * @return returns default message provided by user in cofing.xml/sharedPreferences
       */
      private String defaultMessageTextInNotification() {
        //check if have cached copy of this option
          if (TextUtils.isEmpty(defaultOfflineMessage)) {
              SharedPreferences config = this.getApplicationContext().getSharedPreferences(PREFS_NAME,0);
              if (config != null) {
                  defaultOfflineMessage = config.getString(DEFAULT_MESSAGE_PREF, DEFAULT_MESSAGE_TEXT);
              }
          }
          return defaultOfflineMessage;
      }
  }
  