package com.manning.aip.lifecycle;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;

// logcat filterspec
// adb -e logcat "*:s LifecycleExplorer:v"

// see also: adb shell dumpsys activity

/**
 * 
 * Autorzy aplikacji na Androida powinni dobrze rozumieć cykl życia i pokrewieństwo
 * zadań w aktywności. Niniejsza klasa pomaga zobaczyć, jak platforma obsługuje
 * cykl życia i zadania (używamy tu komunikatów Toast i rejestrujemy każde wywołanie).  
 * 
 * Cztery stany aktywności:
 * ACTIVE/RUNNING (działa na pierwszym planie)
 * PAUSED (nie działa na pierwszym planie, ale wciąż widoczna; częściowo 
 * zasłania ją inna aktywność, niezajmująca całego ekranu)
 * STOPPED (jest całkowicie zasłonięta przez inną aktywność)
 * KILLED (jest wstrzymana lub zatrzymana; może zostać zakończona lub usunięta)
 * 
 * Trzeba pamiętać o trzech pętlach:
 * CAŁY CZAS ŻYCIA - od onCreate do onDestroy
 * CZAS ŻYCIA, KIEDY AKTYWNOŚĆ JEST WIDOCZNA - od onStart do onStop
 * CZAS ŻYCIA NA PIERWSZYM PLANIE - od onResume do onPause
 * 
 * Trzy najważniejsze metody (istnieją też inne):
 * onCreate
 * onResume
 * onPause
 * 
 * http://developer.android.com/intl/de/reference/android/app/Activity.html
 * 
 * Uwaga: Użyj instrukcji logcat filterspec, aby zobaczyć komunikaty związane z debugowaniem:
 * adb -e logcat "*:s LifecycleExplorer:v"
 * 
 * Uwaga: Podaj false w konstruktorze, aby wyłączyć powiadomienia (ich duża liczba spowalnia aplikację).
 * 
 * @author ccollins
 *
 */
public abstract class LifecycleActivity extends Activity {

   private static final String LOG_TAG = "LifecycleExplorer";

   private NotificationManager notifyMgr;
   // Przy wartości domyślnej true (lub przekazaniu jej do konstruktora) aplikacja wysyła
   // powiadomienia. Jeśli jest ich dużo, aplikacja może działać powoli. Warto jednak
   // zobaczyć, co się w niej dzieje.
   private boolean enableNotifications = true;
   
   private final String className;

   public LifecycleActivity() {
      super();
      this.className = this.getClass().getName();
   }

   public LifecycleActivity(final boolean enableNotifications) {
      this();
      this.enableNotifications = enableNotifications;
   }

   @Override
   public void onCreate(Bundle savedInstanceState) {      
      super.onCreate(savedInstanceState);
      notifyMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
      debugEvent("onCreate");
   }

   @Override
   protected void onStart() {      
      debugEvent("onStart");
      super.onStart();      
   }

   @Override
   protected void onResume() {      
      debugEvent("onResume");
      super.onResume();      
   }

   @Override
   protected void onPause() {
      debugEvent("onPause");
      super.onPause();
   }

   @Override
   protected void onStop() {
      debugEvent("onStop");
      super.onStop();
   }

   @Override
   protected void onDestroy() {
      debugEvent("onDestroy");
      super.onDestroy();
   }

   //
   // Metody związane ze stanem.
   //
   @Override
   protected void onRestoreInstanceState(Bundle savedInstanceState) {      
      debugEvent("onRestoreInstanceState");
      super.onRestoreInstanceState(savedInstanceState);      
   }

   @Override
   protected void onSaveInstanceState(Bundle outState) {      
      debugEvent("onSaveInstanceState");
      super.onSaveInstanceState(outState);      
   }

   //
   // Metod związane z konfiguracją. 
   //
   @Override
   public void onConfigurationChanged(Configuration newConfig) {      
      debugEvent("onConfigurationChanged");
      super.onConfigurationChanged(newConfig);      
   }

   @Override
   public Object onRetainNonConfigurationInstance() {
      debugEvent("onRetainNonConfigurationInstance");
      return super.onRetainNonConfigurationInstance();
   }

   //
   // Inne przydatne metody aktywności.
   //
   @Override
   public boolean isFinishing() {
      debugEvent("isFinishing");
      return super.isFinishing();
   }

   @Override
   public void finish() {
      super.finish();
   }

   @Override
   public void onLowMemory() {
      Toast.makeText(this, "onLowMemory", Toast.LENGTH_SHORT).show();
      super.onLowMemory();
   }

   //
   // Metoda pomocnicza do wyświetlania powiadomień.
   //
   private void debugEvent(final String method) {
      long ts = System.currentTimeMillis();
      Log.d(LOG_TAG, " *** " + method + " " + className + " " + ts);
      if (enableNotifications) {
         Notification notification = new Notification(android.R.drawable.star_big_on, "Zdarzenie cyklu życia: " + method, 0L);
         RemoteViews notificationContentView = new RemoteViews(getPackageName(), R.layout.custom_notification_layout);
         notification.contentView = notificationContentView;
         notification.contentIntent = PendingIntent.getActivity(this, 0, null, 0);
         notification.flags |= Notification.FLAG_AUTO_CANCEL;
         notificationContentView.setImageViewResource(R.id.image, android.R.drawable.btn_star);
         notificationContentView.setTextViewText(R.id.lifecycle_class, getClass().getName());
         notificationContentView.setTextViewText(R.id.lifecycle_method, method);
         notificationContentView.setTextColor(R.id.lifecycle_method, R.color.black);
         notificationContentView.setTextViewText(R.id.lifecycle_timestamp, Long.toString(ts));
         notifyMgr.notify((int) System.currentTimeMillis(), notification);
      }
   }
}