// Path: kraken_lib/src/main/java/com/github/marcosalis/kraken/cache/ContentCache.java
// @Beta
// public enum CacheSource {
//     MEMORY,
//     DISK,
//     NETWORK;
// }
// 
// Path: kraken_lib/src/main/java/com/github/marcosalis/kraken/cache/bitmap/AnimationMode.java
// @Beta
// public enum AnimationMode {
//     /**
//      * Use no animation (same as using a normal {@link BitmapAsyncSetter})
//      */
//     NEVER,
//     /**
//      * Animate only if the bitmap is not already in the memory caches
//      */
//     NOT_IN_MEMORY,
//     /**
//      * Animate only if the bitmap was loaded from network
//      */
//     FROM_NETWORK,
//     /**
//      * Always animate (use with care: the performance impact can be noticeable when scrolling long
//      * lists of bitmaps)
//      */
//     ALWAYS;
// }
// 
// Path: kraken_lib/src/main/java/com/github/marcosalis/kraken/cache/bitmap/BitmapCache.java
// @Beta
// public interface OnBitmapSetListener {
// 
//     /**
//      * Called from the UI thread when the retrieved bitmap image has been set into the {@link
//      * ImageView}
//      *
//      * @param key    The {@link CacheUrlKey} of the bitmap
//      * @param bitmap The set {@link Bitmap}
//      * @param source The {@link CacheSource} of the bitmap
//      */
//     public void onBitmapSet(@NonNull CacheUrlKey key, @NonNull Bitmap bitmap,
//                             @NonNull CacheSource source);
// }
// 
// Path: kraken_lib/src/main/java/com/github/marcosalis/kraken/cache/keys/CacheUrlKey.java
// @Beta
// @SuppressLint("ParcelCreator")
// public interface CacheUrlKey extends CacheKey, Parcelable {
// 
//     /**
//      * Gets the hash string used as a key
//      */
//     @NonNull
//     public String hash();
// 
//     /**
//      * Gets the string URL hold by this {@link CacheUrlKey}
//      */
//     @NonNull
//     public String getUrl();
// 
// }


import javax.annotation.concurrent.ThreadSafe;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import com.github.marcosalis.kraken.cache.ContentCache.CacheSource;
import com.github.marcosalis.kraken.cache.bitmap.AnimationMode;
import com.github.marcosalis.kraken.cache.bitmap.BitmapCache.OnBitmapSetListener;
import com.github.marcosalis.kraken.cache.keys.CacheUrlKey;
import com.google.common.annotations.Beta;
     * @param bitmap    The {@link Bitmap} to set
     * @param source    The {@link CacheSource} from where the bitmap was loaded
     */
    protected void setImageBitmap(@NonNull final ImageView imageView, @NonNull Bitmap bitmap,
                                  @NonNull CacheSource source) {
        // only animate when the bitmap source is compatible with the set mode
        if (shouldAnimate(source, mAnimationMode)) {
            final Animation animation = imageView.getAnimation();
            if (animation != null) { // reuse animation
                if (animation.hasEnded()) {
                    // we don't want to animate if we're just setting the same
                    // bitmap again in the same view (can happen when scrolling
                    // back and forth in a long list)
                    final Drawable drawable = imageView.getDrawable();
                    if (drawable instanceof BitmapDrawable) {
                        final Bitmap oldBitmap = ((BitmapDrawable) drawable).getBitmap();
                        if (!bitmap.equals(oldBitmap)) { // different bitmap
                            animation.startNow();
                            if (BITMAP_DEBUG) { // debugging
                                Log.w(TAG,
                                        "Reusing ended animation in reused view"
                                                + imageView.hashCode());
                            }
                        } else {
                            if (BITMAP_DEBUG) { // debugging
                                Log.w(TAG, "Same bitmap, do not animate " + imageView.hashCode());
                            }
                        }
                    } else {
                        animation.startNow();
// Path: kraken_lib/src/main/java/com/github/marcosalis/kraken/cache/ContentCache.java
// @Beta
// public enum CacheSource {
//     MEMORY,
//     DISK,
//     NETWORK;
// }
// 
// Path: kraken_lib/src/main/java/com/github/marcosalis/kraken/cache/bitmap/AnimationMode.java
// @Beta
// public enum AnimationMode {
//     /**
//      * Use no animation (same as using a normal {@link BitmapAsyncSetter})
//      */
//     NEVER,
//     /**
//      * Animate only if the bitmap is not already in the memory caches
//      */
//     NOT_IN_MEMORY,
//     /**
//      * Animate only if the bitmap was loaded from network
//      */
//     FROM_NETWORK,
//     /**
//      * Always animate (use with care: the performance impact can be noticeable when scrolling long
//      * lists of bitmaps)
//      */
//     ALWAYS;
// }
// 
// Path: kraken_lib/src/main/java/com/github/marcosalis/kraken/cache/bitmap/BitmapCache.java
// @Beta
// public interface OnBitmapSetListener {
// 
//     /**
//      * Called from the UI thread when the retrieved bitmap image has been set into the {@link
//      * ImageView}
//      *
//      * @param key    The {@link CacheUrlKey} of the bitmap
//      * @param bitmap The set {@link Bitmap}
//      * @param source The {@link CacheSource} of the bitmap
//      */
//     public void onBitmapSet(@NonNull CacheUrlKey key, @NonNull Bitmap bitmap,
//                             @NonNull CacheSource source);
// }
// 
// Path: kraken_lib/src/main/java/com/github/marcosalis/kraken/cache/keys/CacheUrlKey.java
// @Beta
// @SuppressLint("ParcelCreator")
// public interface CacheUrlKey extends CacheKey, Parcelable {
// 
//     /**
//      * Gets the hash string used as a key
//      */
//     @NonNull
//     public String hash();
// 
//     /**
//      * Gets the string URL hold by this {@link CacheUrlKey}
//      */
//     @NonNull
//     public String getUrl();
// 
// }


// Path: kraken_lib/src/main/java/com/github/marcosalis/kraken/cache/bitmap/internal/BitmapAnimatedAsyncSetter.java
import javax.annotation.concurrent.ThreadSafe;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import com.github.marcosalis.kraken.cache.ContentCache.CacheSource;
import com.github.marcosalis.kraken.cache.bitmap.AnimationMode;
import com.github.marcosalis.kraken.cache.bitmap.BitmapCache.OnBitmapSetListener;
import com.github.marcosalis.kraken.cache.keys.CacheUrlKey;
import com.google.common.annotations.Beta;

     * @param bitmap    The {@link Bitmap} to set
     * @param source    The {@link CacheSource} from where the bitmap was loaded
     */
    protected void setImageBitmap(@NonNull final ImageView imageView, @NonNull Bitmap bitmap,
                                  @NonNull CacheSource source) {
        // only animate when the bitmap source is compatible with the set mode
        if (shouldAnimate(source, mAnimationMode)) {
            final Animation animation = imageView.getAnimation();
            if (animation != null) { // reuse animation
                if (animation.hasEnded()) {
                    // we don't want to animate if we're just setting the same
                    // bitmap again in the same view (can happen when scrolling
                    // back and forth in a long list)
                    final Drawable drawable = imageView.getDrawable();
                    if (drawable instanceof BitmapDrawable) {
                        final Bitmap oldBitmap = ((BitmapDrawable) drawable).getBitmap();
                        if (!bitmap.equals(oldBitmap)) { // different bitmap
                            animation.startNow();
                            if (BITMAP_DEBUG) { // debugging
                                Log.w(TAG,
                                        "Reusing ended animation in reused view"
                                                + imageView.hashCode());
                            }
                        } else {
                            if (BITMAP_DEBUG) { // debugging
                                Log.w(TAG, "Same bitmap, do not animate " + imageView.hashCode());
                            }
                        }
                    } else {
                        animation.startNow();
                        if (BITMAP_DEBUG) { // debugging