package com.wrapp.android.webimage;

import android.graphics.drawable.Drawable;

import java.net.URL;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;

public class ImageLoader {
  private static final int NUM_WORKERS = 1;

  private static ImageLoader staticInstance;
  private final Queue<ImageRequest> pendingRequests = new LinkedList<ImageRequest>();
  private final Worker[] workerPool = new Worker[NUM_WORKERS];
  // TODO: This will be necessary with multiple worker threads
  // private final ImageRequest[] runningRequests = new ImageRequest[NUM_WORKERS];


  private static class Worker extends Thread {
    private int index;

    public Worker(int index) {
      this.index = index;
    }

    @Override
    public void run() {
      final Queue<ImageRequest> requestQueue = getInstance().pendingRequests;
      ImageRequest request;
      while(true) {
        synchronized(requestQueue) {
          while(requestQueue.isEmpty()) {
            try {
              requestQueue.wait();
            }
            catch(InterruptedException e) {
              // Log, but otherwise ignore. Not a big deal.
              LogWrapper.logException(e);
            }
          }

          request = requestQueue.poll();
          Iterator requestIterator = requestQueue.iterator();
          while(requestIterator.hasNext()) {
            ImageRequest checkRequest = (ImageRequest)requestIterator.next();
            if(request.listener.equals(checkRequest.listener)) {
              if(request.imageUrl.equals(checkRequest.imageUrl)) {
                // Ignore duplicate requests. This is common when doing view recycling in list adapters.
                requestIterator.remove();
              }
              else {
                // If this request in the queue was made by the same listener but is for a new URL,
                // then use that request instead and remove it from the queue.
                request = checkRequest;
                requestIterator.remove();
              }
            }
          }
        }

        processRequest(request);
      }
    }

    private void processRequest(ImageRequest request) {
      Drawable drawable = ImageCache.loadImage(request);
      request.listener.onDrawableLoaded(drawable);

      // TODO: Handle running requests queue
      /*
      final ImageRequest[] runningRequests = getInstance().runningRequests;
      synchronized(runningRequests) {
        runningRequests[index] = request;
        drawable = ImageCache.loadImage(request);
      }
      synchronized(runningRequests) {
        if(request != null) {
          request.listener.onDrawableLoaded(drawable);
          runningRequests[index] = null;
        }
        else {
          LogWrapper.logMessage("Interrupted, returning");
        }
      }
      */
    }
  }


  private static ImageLoader getInstance() {
    if(staticInstance == null) {
      staticInstance = new ImageLoader();
    }
    return staticInstance;
  }

  private ImageLoader() {
    for(int i = 0; i < NUM_WORKERS; i++) {
      workerPool[i] = new Worker(i);
      workerPool[i].start();
    }
  }

  public static void load(URL imageUrl, ImageRequest.Listener listener, boolean cacheInMemory) {
    // TODO: This might be too much work in the GUI thread. Move to a worker?

    Queue<ImageRequest> requestQueue = getInstance().pendingRequests;
/*
      synchronized(requestQueue) {
      Iterator requestIterator = requestQueue.iterator();
      while(requestIterator.hasNext()) {
        ImageRequest request = (ImageRequest)requestIterator.next();
        if(request.listener.equals(listener)) {
          if(request.imageUrl.equals(imageUrl)) {
            // Ignore duplicate requests. This is common when doing view recycling in list adapters
            return;
          }
          else {
            // If the listener is the same but the request is for a new URL, remove the previous
            // request from the pending queue
            requestIterator.remove();
          }
        }
      }
      */

/*
      final ImageRequest[] runningRequests = getInstance().runningRequests;
      synchronized(runningRequests) {
        for(int i = 0; i < runningRequests.length; i++) {
          ImageRequest request = runningRequests[i];
          if(request != null) {
            if(request.listener.equals(listener)) {
              if(request.imageUrl.equals(imageUrl)) {
                // Ignore duplicate requests. This is common when doing view recycling in list adapters
                return;
              }
              else {
                // Null out the running request in this index. The job will continue running, but when
                // it returns it will skip notifying the listener and start processing the next job in
                // the pending request queue.
                runningRequests[i] = null;
              }
            }
          }
        }
      }
    }
*/

    synchronized(requestQueue) {
      requestQueue.add(new ImageRequest(imageUrl, listener, cacheInMemory));
      // TODO: Use notifyAll() instead?
      requestQueue.notify();
    }
  }

  public static void cancelAllRequests() {
    final Queue<ImageRequest> requestQueue = getInstance().pendingRequests;
    synchronized(requestQueue) {
      requestQueue.clear();
    }
  }
}

@@ -248,11 +248,10 @@
 S = 
-1;%0A
+2;
 %0A  p
@@ -347,388 +347,58 @@
 ests
- = new LinkedList%3CImageRequest%3E();%0A  private final Worker%5B%5D workerPool = new Worker%5BNUM_WORKERS%5D;%0A  // TODO: This will be necessary with multiple worker threads%0A  // private final ImageRequest%5B%5D runningRequests = new ImageRequest%5BNUM_WORKERS%5D;%0A%0A%0A  private static class Worker extends Thread %7B%0A    private int index;%0A%0A    public Worker(int index) %7B%0A      this.index = index;%0A    %7D%0A
+;%0A%0A%0A  private static class Worker extends Thread %7B
 %0A   
@@ -2681,24 +2681,135 @@
 eLoader() %7B%0A
+    pendingRequests = new LinkedList%3CImageRequest%3E();%0A    final Worker%5B%5D workerPool = new Worker%5BNUM_WORKERS%5D;%0A
     for(int 
@@ -2872,17 +2872,16 @@
  Worker(
-i
 );%0A     

Use 2 workers, initialize in constructor