/*
 * Copyright (C) 2012 Brian Muramatsu
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.btmura.android.reddit.widget;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.util.LruCache;
import android.view.View;

public class ThumbnailLoader {

    private static final String TAG = "ThumbnailLoader";

    private static final BitmapCache BITMAP_CACHE = new BitmapCache(2 * 1024 * 1024);

    public void setThumbnail(ThingView v, String url) {
        Bitmap b = BITMAP_CACHE.get(url);
        v.setThumbnail(b);
        if (b == null) {
            LoadThumbnailTask task = (LoadThumbnailTask) v.getTag();
            if (task == null || !url.equals(task.url)) {
                if (task != null) {
                    task.cancel(true);
                }
                task = new LoadThumbnailTask(v, url);
                v.setTag(task);
                task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
            }
        }
        v.setVisibility(View.VISIBLE);
    }

    public void clearThumbnail(ThingView v) {
        LoadThumbnailTask task = (LoadThumbnailTask) v.getTag();
        if (task != null) {
            task.cancel(true);
            v.setTag(null);
        }
        v.removeThumbnail();
    }

    static class BitmapCache extends LruCache<String, Bitmap> {
        BitmapCache(int size) {
            super(size);
        }

        @Override
        protected int sizeOf(String key, Bitmap value) {
            return value.getByteCount();
        }
    }

    class LoadThumbnailTask extends AsyncTask<Void, Void, Bitmap> {

        private final WeakReference<ThingView> ref;
        private final String url;

        LoadThumbnailTask(ThingView v, String url) {
            this.ref = new WeakReference<ThingView>(v);
            this.url = url;
        }

        @Override
        protected Bitmap doInBackground(Void... params) {
            HttpURLConnection conn = null;
            try {
                URL u = new URL(url);
                conn = (HttpURLConnection) u.openConnection();
                return BitmapFactory.decodeStream(conn.getInputStream());
            } catch (MalformedURLException e) {
                Log.e(TAG, url, e);
            } catch (IOException e) {
                Log.e(TAG, url, e);
            } finally {
                if (conn != null) {
                    conn.disconnect();
                }
            }
            return null;
        }

        @Override
        protected void onPostExecute(Bitmap b) {
            if (b != null) {
                BITMAP_CACHE.put(url, b);
            }
            ThingView v = ref.get();
            if (v != null && equals(v.getTag())) {
                if (b != null) {
                    v.setThumbnail(b);
                }
                v.setTag(null);
            }
        }
    }
}

@@ -1254,24 +1254,55 @@
 E.get(url);%0A
+        synchronized (v) %7B%0A    
         v.se
@@ -1320,24 +1320,28 @@
 b);%0A        
+    
 if (b == nul
@@ -1349,32 +1349,36 @@
 ) %7B%0A            
+   
+ 
 LoadThumbnailTas
@@ -1410,32 +1410,36 @@
 sk) v.getTag();%0A
+    
             if (
@@ -1487,32 +1487,36 @@
                 
+    
 if (task != null
@@ -1531,32 +1531,36 @@
                 
+ 
+   
 task.cancel(true
@@ -1570,34 +1570,40 @@
                 
-%7D%0A
+    %7D%0A  
                 
@@ -1598,24 +1598,26 @@
             
+  
 task = new L
@@ -1650,32 +1650,36 @@
                 
+    
 v.setTag(task);%0A
@@ -1690,24 +1690,28 @@
             
+   
+ 
 task.execute
@@ -1758,34 +1758,42 @@
 R);%0A            
-%7D%0A
+    %7D%0A    
         %7D%0A      
@@ -1790,24 +1790,28 @@
   %7D%0A        
+    
 v.setVisibil
@@ -1829,16 +1829,26 @@
 SIBLE);%0A
+        %7D%0A
     %7D%0A%0A 
@@ -1888,24 +1888,55 @@
 ngView v) %7B%0A
+        synchronized (v) %7B%0A    
         Load
@@ -1988,32 +1988,36 @@
 tTag();%0A        
+   
+ 
 if (task != null
@@ -2024,32 +2024,36 @@
 ) %7B%0A            
+    
 task.cancel(true
@@ -2047,32 +2047,36 @@
 k.cancel(true);%0A
+    
             v.se
@@ -2087,34 +2087,42 @@
 (null);%0A        
-%7D%0A
+    %7D%0A    
         v.remove
@@ -2130,24 +2130,34 @@
 humbnail();%0A
+        %7D%0A
     %7D%0A%0A    s
@@ -3542,24 +3542,59 @@
  ref.get();%0A
+            synchronized (v) %7B%0A    
             
@@ -3640,32 +3640,36 @@
                 
+    
 if (b != null) %7B
@@ -3661,32 +3661,36 @@
 f (b != null) %7B%0A
+    
                 
@@ -3720,34 +3720,42 @@
                 
+ 
-%7D%0A
+   %7D%0A    
                 
@@ -3762,32 +3762,50 @@
 v.setTag(null);%0A
+                %7D%0A
             %7D%0A  

Add some thumbnail loading synchronization