package com.webimageloader.ext;

import java.io.File;

import com.webimageloader.ImageLoader;
import com.webimageloader.loader.MemoryCache;
import com.webimageloader.util.IOUtil;

import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.Application;
import android.content.Context;
import android.util.Log;

/**
 * Helper class for creating a global {@link ImageLoader} with sane defaults.
 *
 * @author Alexander Blom <alexanderblom.se>
 *
 */
public class ImageLoaderApplication extends Application {
    private static final String TAG = "ImageLoaderApplication";

    public static final String IMAGE_LOADER_SERVICE = "image_loader";

    private static final int MEMORY_DIVIDER = 8;
    private static final int DISK_CACHE_SIZE = 10 * 1024 * 1024;

    private ImageLoader imageLoader;

    @Override
    public void onCreate() {
        super.onCreate();

        imageLoader = getBuilder().build();
    }

    @Override
    public Object getSystemService(String name) {
        if (IMAGE_LOADER_SERVICE.equals(name)) {
            return imageLoader;
        } else {
            return super.getSystemService(name);
        }
    }

    @Override
    public void onTerminate() {
        super.onTerminate();

        imageLoader.destroy();
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();

        MemoryCache memoryCache = imageLoader.getMemoryCache();
        if (memoryCache != null) {
            Log.d(TAG, "onLowMemory() called, eviciting all bitmaps");
            memoryCache.evictAll();
        }
    }

    @Override
    @TargetApi(14)
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);

        MemoryCache memoryCache = imageLoader.getMemoryCache();
        if (memoryCache == null) {
            return;
        }

        if (level >= TRIM_MEMORY_MODERATE) {
            // Nearing middle of list of cached background apps
            // Evict our entire bitmap cache
            Log.d(TAG, "onTrimMemory(), level>=TRIM_MEMORY_MODERATE called, eviciting all bitmaps");
            memoryCache.evictAll();
        } else if (level >= TRIM_MEMORY_BACKGROUND) {
            // Entering list of cached background apps
            // Evict oldest half of our bitmap cache
            Log.d(TAG, "onTrimMemory(), level>=TRIM_MEMORY_BACKGROUND called, evicing half of all bitmaps");
            memoryCache.trimToSize(memoryCache.size() / 2);
        }
    }

    public static ImageLoader getLoader(Context context) {
        return (ImageLoader) context.getApplicationContext().getSystemService(IMAGE_LOADER_SERVICE);
    }

    protected ImageLoader.Builder getBuilder() {
        // Get memory class of this device, exceeding this amount will throw an
        // OutOfMemory exception.
        ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        int memClass = am.getMemoryClass();

        // Use part of the available memory for memory cache.
        final int memoryCacheSize = 1024 * 1024 * memClass / MEMORY_DIVIDER;

        Log.d(TAG, "Using memory cache of size: " + humanReadableByteCount(memoryCacheSize, false));
        Log.d(TAG, "Using disk cache of size: " + humanReadableByteCount(DISK_CACHE_SIZE, false));

        File cacheDir = IOUtil.getDiskCacheDir(this, "images");
        return new ImageLoader.Builder()
                .enableDiskCache(cacheDir, DISK_CACHE_SIZE)
                .enableMemoryCache(memoryCacheSize)
                .supportResources(getContentResolver());
    }

    // http://stackoverflow.com/a/3758880/253583
    private static String humanReadableByteCount(long bytes, boolean si) {
        int unit = si ? 1000 : 1024;
        if (bytes < unit) return bytes + " B";
        int exp = (int) (Math.log(bytes) / Math.log(unit));
        String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i");
        return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
    }
}

@@ -418,16 +418,96 @@
 faults.%0A
+ * Set this as your %7B@code android:application%7D in %7B@code AndroidManifest.xml%7D.%0A
  *%0A * @a
@@ -546,19 +546,16 @@
 lom.se%3E%0A
- *%0A
  */%0Apubl
@@ -740,24 +740,86 @@
 e_loader%22;%0A%0A
+    private static final String CACHE_FOLDER_NAME = %22images%22;%0A
     private 
@@ -2597,24 +2597,186 @@
    %7D%0A    %7D%0A%0A
+    /**%0A     * Get the loader provided by this %7B@link Application%7D%0A     *%0A     * @param context the current context%0A     * @return an %7B@link ImageLoader%7D%0A     */%0A
     public s
@@ -2926,24 +2926,766 @@
 CE);%0A    %7D%0A%0A
+    /**%0A     * Get folder name to use for the disk cache, by default %22images%22%0A     *%0A     * @return the folder name%0A     */%0A    protected String getCacheFolderName() %7B%0A        return CACHE_FOLDER_NAME;%0A    %7D%0A%0A    /**%0A     * Get the size of the disk cache, by default 10Mb%0A     *%0A     * @return the disk cache size%0A     */%0A    protected int getDiskCacheSize() %7B%0A        return DISK_CACHE_SIZE;%0A    %7D%0A%0A    /**%0A     * The divider of the total memory to use for memory cache%0A     *%0A     * @return the memory divider%0A     */%0A    protected int getMemoryDivider() %7B%0A        return MEMORY_DIVIDER;%0A    %7D%0A%0A    /**%0A     * The builder used to construct the %7B@link ImageLoader%7D used by this %7B@link Application%7D.%0A     *%0A     * @return the builder%0A     */%0A
     protecte
@@ -4094,32 +4094,80 @@
 Class / 
-MEMORY_DIVIDER;%0A
+getMemoryDivider();%0A%0A        int diskCache = getDiskCacheSize();
 %0A       
@@ -4333,31 +4333,25 @@
 teCount(
-DISK_CACHE_SIZE
+diskCache
 , false)
@@ -4407,24 +4407,36 @@
 r(this, 
-%22images%22
+getCacheFolderName()
 );%0A     
@@ -4514,31 +4514,25 @@
 cheDir, 
-DISK_CACHE_SIZE
+diskCache
 )%0A      

Add methods for overriding in ImageLoaderApplication