package com.webimageloader.loader;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import com.webimageloader.transformation.Transformation;

import android.graphics.Bitmap;

public class LoaderManager {
    private MemoryCache memoryCache;

    private DiskLoader diskLoader;
    private NetworkLoader networkLoader;
    private TransformingLoader transformingLoader;
    private MemoryLoader memoryLoader;

    private List<Loader> standardChain;

    private PendingRequests pendingRequests;

    public interface Listener {
        void onLoaded(Bitmap b);
        void onError(Throwable t);
    }

    public LoaderManager(MemoryCache memoryCache, DiskLoader diskLoader, NetworkLoader networkLoader) {
        this.memoryCache = memoryCache;
        this.diskLoader = diskLoader;
        this.networkLoader = networkLoader;

        transformingLoader = new TransformingLoader();
        if (memoryCache != null) {
            memoryLoader = new MemoryLoader(memoryCache);
        }

        standardChain = new ArrayList<Loader>();
        add(standardChain, diskLoader);
        standardChain.add(networkLoader);

        // Ensure the standard chain is not modified and is safe to iterate
        // over in multiple threads
        standardChain = Collections.unmodifiableList(standardChain);

        pendingRequests = new PendingRequests(memoryCache, standardChain);
    }

    public MemoryCache getMemoryCache() {
        return memoryCache;
    }

    public Bitmap getBitmap(Object tag, LoaderRequest request) {
        return pendingRequests.getBitmap(tag, request);
    }

    public Bitmap load(Object tag, LoaderRequest request, final Listener listener) {
        Bitmap b = pendingRequests.getBitmap(tag, request);
        if (b != null) {
            return b;
        }

        Loader.Listener l = pendingRequests.addRequest(tag, request, listener);

        // A request is already pending, don't load anything
        if (l == null) {
            return null;
        }

        List<Loader> chain = standardChain;

        Transformation transformation = request.getTransformation();
        if (transformation != null) {
            // Use special chain with transformation
            ArrayList<Loader> loaderChain = new ArrayList<Loader>();
            add(loaderChain, diskLoader);
            add(loaderChain, transformingLoader);
            add(loaderChain, memoryLoader);
            add(loaderChain, diskLoader);
            add(loaderChain, networkLoader);

            chain = loaderChain;
        }

        Iterator<Loader> it = chain.iterator();
        it.next().load(request, it, l);

        return null;
    }

    public void close() {
        if (diskLoader != null) {
            diskLoader.close();
        }
    }

    private static <T> void add(List<T> list, T item) {
        if (item != null) {
            list.add(item);
        }
    }
}

@@ -498,24 +498,70 @@
 andardChain;
+%0A    private List%3CLoader%3E transformationChain;
 %0A%0A    privat
@@ -1081,32 +1081,65 @@
 he);%0A        %7D%0A%0A
+        // Create standard chain%0A
         standard
@@ -1246,32 +1246,370 @@
 etworkLoader);%0A%0A
+        // Create transformation chain%0A        transformationChain = new ArrayList%3CLoader%3E();%0A        add(transformationChain, diskLoader);%0A        add(transformationChain, transformingLoader);%0A        add(transformationChain, memoryLoader);%0A        add(transformationChain, diskLoader);%0A        add(transformationChain, networkLoader);%0A%0A
         // Ensur
@@ -1772,16 +1772,97 @@
 dChain);
+%0A        transformationChain = Collections.unmodifiableList(transformationChain);
 %0A%0A      
@@ -2560,113 +2560,76 @@
     
-List%3CLoader%3E chain = standardChain;%0A%0A        Transformation transformation = request.getTransformation();
+// Use different chains depending if we have a transformation or not
 %0A   
@@ -2637,13 +2637,9 @@
     
-if (t
+T
 rans
@@ -2652,58 +2652,24 @@
 ion 
-!= null) %7B%0A            // Use special chain with t
+t = request.getT
 rans
@@ -2677,16 +2677,19 @@
 ormation
+();
 %0A       
@@ -2693,17 +2693,8 @@
     
-    Array
 List
@@ -2706,117 +2706,43 @@
 er%3E 
-loaderChain = new ArrayList%3CLoader%3E();%0A            add(loaderChain, diskLoader);%0A            add(loader
+chain = t == null ? standard
 Chain
-,
+ :
  tra
@@ -2751,194 +2751,19 @@
 form
-ingLoader);%0A            add(loaderChain, memoryLoader);%0A            add(loaderChain, diskLoader);%0A            add(loaderChain, networkLoader);%0A%0A            chain = loaderChain;%0A        %7D
+ationChain;
 %0A%0A  

Create transformation thread up front