package com.manning.aip.dealdroid;

import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.preference.PreferenceManager;
import android.util.Log;

import com.manning.aip.dealdroid.model.Item;
import com.manning.aip.dealdroid.model.Section;
import com.manning.aip.dealdroid.xml.DailyDealsFeedParser;
import com.manning.aip.dealdroid.xml.DailyDealsXmlPullFeedParser;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DealDroidApp extends Application {

   private ConnectivityManager cMgr;
   private DailyDealsFeedParser parser;
   private List<Section> sectionList;
   private Map<Long, Bitmap> imageCache;
   private Item currentItem;
   private SharedPreferences prefs;

   //
   // Procedury ustawiające i pobierające.
   //
   public DailyDealsFeedParser getParser() {
      return this.parser;
   }

   public List<Section> getSectionList() {
      return this.sectionList;
   }

   public void setSectionList(List<Section> sectionList) {
      this.sectionList = sectionList;
   }

   public Map<Long, Bitmap> getImageCache() {
      return this.imageCache;
   }

   public Item getCurrentItem() {
      return this.currentItem;
   }

   public void setCurrentItem(Item currentItem) {
      this.currentItem = currentItem;
   }

   public SharedPreferences getPrefs() {
      return this.prefs;
   }

   //
   // Obsługa cyklu życia.
   //
   @Override
   public void onCreate() {
      super.onCreate();
      this.cMgr = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
      this.parser = new DailyDealsXmlPullFeedParser();
      this.sectionList = new ArrayList<Section>(6);
      this.imageCache = new HashMap<Long, Bitmap>();
      this.prefs = PreferenceManager.getDefaultSharedPreferences(this);
   }

   @Override
   public void onTerminate() {
      // Brak gwarancji, że zostanie wywołana.
      super.onTerminate();
   }

   //
   // Stan wcześniejszej oferty (używany przez usługę).
   //
   public List<Long> getPreviousDealIds() {
      List<Long> previousDealIds = new ArrayList<Long>();
      previousDealIds.add(prefs.getLong(Constants.DEAL1, 0));
      previousDealIds.add(prefs.getLong(Constants.DEAL2, 0));
      previousDealIds.add(prefs.getLong(Constants.DEAL3, 0));
      previousDealIds.add(prefs.getLong(Constants.DEAL4, 0));
      previousDealIds.add(prefs.getLong(Constants.DEAL5, 0));
      return previousDealIds;
   }

   public void setPreviousDealIds(List<Long> previousDealIds) {
      // Błąd nigdy nie powinien wystąpić, jeśli jednak 
	  // się zdarzy, warto szybko zgłosić problem.
      if ((previousDealIds == null) || previousDealIds.isEmpty() || previousDealIds.size() > 5) {
         throw new IllegalArgumentException("Błąd - previousDealIds ma wartość null, jest pusta lub większa niż 5");
      }
      Editor editor = prefs.edit();
      editor.putLong(Constants.DEAL1, previousDealIds.get(0));
      editor.putLong(Constants.DEAL2, previousDealIds.get(1));
      editor.putLong(Constants.DEAL3, previousDealIds.get(2));
      editor.putLong(Constants.DEAL4, previousDealIds.get(3));
      // Później dodaliśmy obsługę piątej oferty. Niektórzy użytkownicy mają w pliku tylko
      // cztery oferty.
      // Pewnego dnia eBay udostępniał pięć ofert; zwykle są cztery oferty.
      if (previousDealIds.size() == 4) {
         previousDealIds.add(0L);
      }
      editor.putLong(Constants.DEAL5, previousDealIds.get(4));
      editor.commit();
   }

   public List<Long> parseItemsIntoDealIds(List<Item> items) {
      List<Long> idList = new ArrayList<Long>();
      if ((items != null) && !items.isEmpty()) {
         for (Item item : items) {
            idList.add(item.getItemId());
         }
      }
      return idList;
   }

   //
   // Metody pomocnicze (używane przez więcej niż jedną inną aktywność, 
   // dlatego umieszczono je tutaj. Można umieścić je także w klasie narzędziowej).
   //
   public Bitmap retrieveBitmap(String urlString) {
      Log.d(Constants.LOG_TAG, "Pobieranie rysunku:" + urlString);
      Bitmap bitmap = null;
      try {
         URL url = new URL(urlString);
         // UWAGA - nie ograniczaj się do wywołania "url.openStream()".  
         // Jest to skrócony odpowiednik wywołania openConnection().getInputStream(), który nie ustawia limitu czasu.
         // Wartość domyślna to nieskonczoność, dlatego aplikacja czeka wtedy bez końca na serwer, jeśli ten nie działa.
         // Kilka dodatkowych wierszy pozwala utworzyć poprawne rozwiązanie.         
         URLConnection conn = url.openConnection();     
         conn.setConnectTimeout(3000);
         conn.setReadTimeout(5000);         
         bitmap = BitmapFactory.decodeStream(conn.getInputStream());
      } catch (MalformedURLException e) {
         Log.e(Constants.LOG_TAG, "Wyjątek w czasie pobierania obrazu - błędny adres URL", e);
      } catch (IOException e) {
         Log.e(Constants.LOG_TAG, "Wyjątek w czasie pobierania obrazu - błąd wejścia-wyjścia", e);
      }
      return bitmap;
   }

   public boolean connectionPresent() {
      NetworkInfo netInfo = cMgr.getActiveNetworkInfo();
      if ((netInfo != null) && (netInfo.getState() != null)) {
         return netInfo.getState().equals(State.CONNECTED);
      } 
      return false;
   }
}