package com.ggstudios.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;

import com.jakewharton.disklrucache.DiskLruCache;

import timber.log.Timber;

public class DiskLruImageCache {
	private static final int IO_BUFFER_SIZE = Utils.MB_BYTES * 2;

	private DiskLruCache mDiskCache;
	private CompressFormat mCompressFormat = CompressFormat.JPEG;
	private int mCompressQuality = 70;
	private static final int APP_VERSION = 1;
	private static final int VALUE_COUNT = 1;

	private boolean errorState = false;

	public DiskLruImageCache( Context context,String uniqueName, int diskCacheSize,
			CompressFormat compressFormat, int quality ) {
		try {
			final File diskCacheDir = getDiskCacheDir(context, uniqueName );
			mDiskCache = DiskLruCache.open( diskCacheDir, APP_VERSION, VALUE_COUNT, diskCacheSize );
			mCompressFormat = compressFormat;
			mCompressQuality = quality;
		} catch (IOException e) {
			e.printStackTrace();
			errorState = true;
		}
	}
	
	public boolean isInErrorState() {
		return errorState;
	}

	private boolean writeBitmapToFile( Bitmap bitmap, DiskLruCache.Editor editor )
			throws IOException, FileNotFoundException {
		OutputStream out = null;
		try {
			out = new BufferedOutputStream( editor.newOutputStream( 0 ), IO_BUFFER_SIZE );
			return bitmap.compress( mCompressFormat, mCompressQuality, out );
		} finally {
			if ( out != null ) {
				out.close();
			}
		}
	}

	private File getDiskCacheDir(Context context, String uniqueName) {
		return new File(context.getExternalFilesDir(null), "SplashCache");
	}

	public void put( String key, Bitmap data ) {

		DiskLruCache.Editor editor = null;
		try {
			editor = mDiskCache.edit( key );
			if ( editor == null ) {
				return;
			}

			if( writeBitmapToFile( data, editor ) ) {               
				mDiskCache.flush();
				editor.commit();
                Timber.d("image put on disk cache " + key );
			} else {
				editor.abort();
                Timber.d("ERROR on: image put on disk cache " + key );
			}   
		} catch (IOException e) {
            Timber.d("ERROR on: image put on disk cache " + key );
			try {
				if ( editor != null ) {
					editor.abort();
				}
			} catch (IOException ignored) {
			}           
		}

	}

	public Bitmap getBitmap( String key ) {

		Bitmap bitmap = null;
		DiskLruCache.Snapshot snapshot = null;
		try {

			snapshot = mDiskCache.get( key );
			if ( snapshot == null ) {
				return null;
			}
			final InputStream in = snapshot.getInputStream( 0 );
			if ( in != null ) {
				final BufferedInputStream buffIn = 
						new BufferedInputStream( in, IO_BUFFER_SIZE );
				bitmap = BitmapFactory.decodeStream( buffIn );              
			}   
		} catch ( IOException e ) {
			e.printStackTrace();
		} finally {
			if ( snapshot != null ) {
				snapshot.close();
			}
		}

		Timber.d(bitmap == null ? "" : "image read from disk " + key);

		return bitmap;
	}

    public void remove(String key) {
        try {
            mDiskCache.remove(key);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

	public boolean containsKey( String key ) {

		boolean contained = false;
		DiskLruCache.Snapshot snapshot = null;
		try {
			snapshot = mDiskCache.get( key );
			contained = snapshot != null;
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if ( snapshot != null ) {
				snapshot.close();
			}
		}

		return contained;

	}

	public void clearCache() {
        Timber.d("disk cache CLEARED");
		try {
			mDiskCache.delete();
		} catch ( IOException e ) {
			e.printStackTrace();
		}
	}

	public File getCacheFolder() {
		return mDiskCache.getDirectory();
	}

}

@@ -2522,24 +2522,112 @@
   %0A%09%09%7D%0A%0A%09%7D%0A%0A
+    public Bitmap getBitmap( String key ) %7B%0A        return getBitmap(key, true);%0A    %7D%0A%0A
 %09public Bitm
@@ -2631,33 +2631,32 @@
 itmap getBitmap(
- 
 String key ) %7B%0A%0A
@@ -2645,25 +2645,39 @@
 p(String key
- 
+, boolean retry
 ) %7B%0A%0A%09%09Bitma
@@ -2742,17 +2742,16 @@
 %09%09try %7B%0A
-%0A
 %09%09%09snaps
@@ -3067,27 +3067,24 @@
        %0A%09%09%09%7D
-   
 %0A%09%09%7D catch (
@@ -3118,35 +3118,234 @@
 ntStackTrace();%0A
-
 %09%09%7D
+ catch (OutOfMemoryError e) %7B%0A            if (retry) %7B%0A                System.gc();%0A                return getBitmap(key, false);%0A            %7D else %7B%0A                throw e;%0A            %7D%0A        %7D
  finally %7B%0A%09%09%09if

Decrease chances of crashing