package pub.util;

import java.io.File;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;

import com.baidu.mapapi.map.ItemizedOverlay;

import pri.h.semap.messageOverlay;
import pri.z.show.R;
import pub.application.SEMapApplication;
import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.media.ThumbnailUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.support.v4.util.LruCache;
import android.widget.ImageView;

/**
 * 图片加载类
 */
public class ImageManagerMap {

	private static ImageManagerMap imageManager;
	public LruCache<String, Bitmap> mMemoryCache;
	private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 
	private static final String DISK_CACHE_SUBDIR = "thumbnails";
	public DiskLruCache mDiskCache;
	private static SEMapApplication myapp;

	/** 图片加载队列，后进先出 */
	private Stack<ImageRef> mImageQueue = new Stack<ImageRef>();

	/** 图片请求队列，先进先出，用于存放已发送的请求。 */
	private Queue<ImageRef> mRequestQueue = new LinkedList<ImageRef>();

	/** 图片加载线程消息处理器 */
	private Handler mImageLoaderHandler;

	/** 图片加载线程是否就绪 */
	private boolean mImageLoaderIdle = true;

	/** 请求图片 */
	private static final int MSG_REQUEST = 1;
	/** 图片加载完成 */
	private static final int MSG_REPLY = 2;
	/** 中止图片加载线程 */
	private static final int MSG_STOP = 3;
	/** 更新某一图片 */
	private static final int MSG_REFRESH_ONE = 4;
	/** 如果图片是从网络加载，则应用渐显动画，如果从缓存读出则不应用动画 */
	private boolean isFromNet = true;

	private static Context mContext;
	/**
	 * 获取单例，只能在UI线程中使用。
	 * 
	 * @param context
	 * @return
	 */
	public static ImageManagerMap from(Context context) {

		mContext = context;
		// 如果不在ui线程中，则抛出异常
		if (Looper.myLooper() != Looper.getMainLooper()) {
			throw new RuntimeException("Cannot instantiate outside UI thread.");
		}

		if (myapp == null) {
			myapp = (SEMapApplication) context.getApplicationContext();
		}

		if (imageManager == null) {
			imageManager = new ImageManagerMap(myapp);
		}

		return imageManager;
	}

	/**
	 * 私有构造函数，保证单例模式
	 * 
	 * @param context
	 */
	private ImageManagerMap(Context context) {
		int memClass = ((ActivityManager) context
				.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
		memClass = memClass > 32 ? 32 : memClass;
		// 使用可用内存的1/8作为图片缓存
		final int cacheSize = 1024 * 1024 * memClass / 8;

		mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {

			protected int sizeOf(String key, Bitmap bitmap) {
				return bitmap.getRowBytes() * bitmap.getHeight();
			}

		};

		File cacheDir = DiskLruCache
				.getDiskCacheDir(context, DISK_CACHE_SUBDIR);
		mDiskCache = DiskLruCache.openCache(context, cacheDir, DISK_CACHE_SIZE);

	}

	/**
	 * 存放图片信息
	 */
	class ImageRef {

		/** 图片对应ImageView控件 */
//		ImageView imageView;
		/** 图片URL地址 */
		String url;
		/** 图片缓存路径 */
		String filePath;
		/** 默认图资源ID */
		int resId;
		int width = 50;
		int height = 50;
		ItemizedOverlay itemizedOverlay ;
		int fence = 0;

		/**
		 * 构造函数
		 * 
		 * @param imageView
		 * @param url
		 * @param resId
		 * @param filePath
		 * @param itemizedOverlay 
		 */
		ImageRef( String url, String filePath, int resId, ItemizedOverlay itemizedOverlay,int fence) {
//			this.imageView = imageView;
			this.url = url;
			this.filePath = filePath;
			this.resId = resId;
			this.itemizedOverlay = itemizedOverlay;
//			this.width = 50;
//			this.height = 50;
		}

		ImageRef( String url, String filePath, int resId,
				int width, int height, ItemizedOverlay itemizedOverlay,int fence) {
			this.url = url;
			this.filePath = filePath;
			this.resId = resId;
			this.width = width;
			this.height = height;
			this.itemizedOverlay = itemizedOverlay;
		}

	}

	/**
	 * 显示图片
	 * 
	 * @param imageView
	 * @param url
	 * @param resId
	 * @param itemizedOverlay 
	 * @param fence 
	 */
	public Drawable displayImage(String url, int resId, ItemizedOverlay itemizedOverlay, int fence) {
		Drawable drawable = null;
		
		
				
		if (url == null || url.equals("")) {
			drawable = mContext.getResources().getDrawable(resId);
			return drawable;
		}

		// 读取map缓存
		Bitmap bitmap = mMemoryCache.get(url);
		if (bitmap != null) {
			drawable =new BitmapDrawable(bitmap);
			return drawable;
		}

		// 生成文件名
		String filePath = urlToFilePath(url);
		if (filePath == null) { 
			return null;
		}

		queueImage(new ImageRef( url, filePath, resId , itemizedOverlay , fence));
		
		return drawable;
	}
	
	public void displayNewImage(ImageView imageView, String url, int resId ,ItemizedOverlay itemizedOverlay,int fence) {
		if (imageView == null) {
			return;
		}
		if (imageView.getTag() != null
				&& imageView.getTag().toString().equals(url)) {
			return;
		}
		
		if(itemizedOverlay == null) {
			return;
		}
		if(itemizedOverlay.getAllItem() == null) {
			return;
		}
		if (resId >= 0) {
			if (imageView.getBackground() == null) {
				imageView.setBackgroundResource(resId);
			}
			imageView.setImageDrawable(null);

		}
		if (url == null || url.equals("")) {
			return;
		}

		// 添加url tag
		imageView.setTag(url);

		// 生成文件名
		String filePath = urlToFilePath(url);
		if (filePath == null) {
			return;
		}

		queueNewImage(new ImageRef( url, filePath, resId , itemizedOverlay,fence));
	}

	/**
	 * 显示图片固定大小图片的缩略图，一般用于显示列表的图片，可以大大减小内存使用
	 * 
	 * @param imageView
	 *            加载图片的控件
	 * @param url
	 *            加载地址
	 * @param resId
	 *            默认图片
	 * @param width
	 *            指定宽度
	 * @param height
	 *            指定高度
	 */
	public void displayImage( String url, int resId,
			int width, int height,ItemizedOverlay itemizedOverlay, int fence) {

		
		if(itemizedOverlay == null) {
			return;
		}
		if(itemizedOverlay.getAllItem() == null) {
			return;
		}
		if (resId >= 0) {

			if (itemizedOverlay.getItem(fence).getMarker() == null) {
				itemizedOverlay.getItem(fence).setMarker(myapp.getResources().getDrawable(resId));
			}

		}
		if (url == null || url.equals("")) {
			return;
		}

		// 添加url tag
//		itemizedOverlay.getItem(fence).setTag(url);
		// 读取map缓存
		Bitmap bitmap = mMemoryCache.get(url + width + height);
		if (bitmap != null) {
			if (!bitmap.isRecycled()) {
				setImageBitmap(itemizedOverlay, bitmap, false , fence);
				
				return;
			}
		}

		// 生成文件名
		String filePath = urlToFilePath(url);
		if (filePath == null) {
			return;
		}

		queueImage(new ImageRef(url, filePath, resId, width, height , itemizedOverlay, fence));
	}

	/**
	 * display new photo
	 * 
	 * @param url
	 * @param width
	 * @param height
	 */
	public void displayNewImage(ImageView imageView, String url, int resId,
			int width, int height , ItemizedOverlay itemizedOverlay,int fence) {
		if (imageView == null) {
			return;
		}
		if (resId >= 0) {

			if (imageView.getBackground() == null) {
				imageView.setBackgroundResource(resId);
			}
			imageView.setImageDrawable(null);

		}
		if (url == null || url.equals("")) {
			return;
		}

		// 添加url tag
		imageView.setTag(url);

		// 生成文件名
		String filePath = urlToFilePath(url);
		if (filePath == null) {
			return;
		}

		queueNewImage(new ImageRef(url, filePath, resId, width,
				height, itemizedOverlay, fence));
	}

	private void queueNewImage(ImageRef imageRef) {
		// 删除已有ImageView
//		Iterator<ImageRef> iterator = mImageQueue.iterator();
//		while (iterator.hasNext()) {
//			if (iterator.next().imageView == imageRef.imageView) {
//				iterator.remove();
//			}
//		}

		// 添加请求
		mImageQueue.push(imageRef);
		sendNewRequest();
	}

	private void sendNewRequest() {
		// 开启图片加载线程
		if (mImageLoaderHandler == null) {
			HandlerThread imageLoader = new HandlerThread("image_loader");
			imageLoader.start();
			mImageLoaderHandler = new ImageLoaderHandler(
					imageLoader.getLooper());
		}

		// 发送请求
		if (mImageLoaderIdle && mImageQueue.size() > 0) {
			ImageRef imageRef = mImageQueue.pop();
			Message message = mImageLoaderHandler.obtainMessage(
					MSG_REFRESH_ONE, imageRef);
			mImageLoaderHandler.sendMessage(message);
			mImageLoaderIdle = false;
			mRequestQueue.add(imageRef);
		}
	}

	public void removeBitmap(String url, int width, int height) {
		// 内存清除
		mMemoryCache.remove(url + width + height);
		// SD卡清除

	}

	/**
	 * 入队，后进先出
	 * 
	 * @param imageRef
	 */
	public void queueImage(ImageRef imageRef) {

		// 删除已有ImageView
//		Iterator<ImageRef> iterator = mImageQueue.iterator();
//		while (iterator.hasNext()) {
//			if (iterator.next().imageView == imageRef.imageView) {
//				iterator.remove();
//			}
//		}

		// 添加请求
		mImageQueue.push(imageRef);
		sendRequest();
	}

	/**
	 * 发送请求
	 */
	private void sendRequest() {

		// 开启图片加载线程
		if (mImageLoaderHandler == null) {
			HandlerThread imageLoader = new HandlerThread("image_loader");
			imageLoader.start();
			mImageLoaderHandler = new ImageLoaderHandler(
					imageLoader.getLooper());
		}

		// 发送请求
		if (mImageLoaderIdle && mImageQueue.size() > 0) {
			ImageRef imageRef = mImageQueue.pop();
			Message message = mImageLoaderHandler.obtainMessage(MSG_REQUEST,
					imageRef);
			mImageLoaderHandler.sendMessage(message);
			mImageLoaderIdle = false;
			mRequestQueue.add(imageRef);
		}
	}

	/**
	 * 图片加载线程
	 */
	class ImageLoaderHandler extends Handler {

		public ImageLoaderHandler(Looper looper) {
			super(looper);
		}

		public void handleMessage(Message msg) {
			if (msg == null)
				return;

			switch (msg.what) {

			case MSG_REQUEST: // 收到请求
				Bitmap bitmap = null;
				Bitmap tBitmap = null;
				if (msg.obj != null && msg.obj instanceof ImageRef) {

					ImageRef imageRef = (ImageRef) msg.obj;
					String url = imageRef.url;
					if (url == null)
						return;
					// 如果本地url即读取sd相册图片，则直接读取，不用经过DiskCache
					if (url.toLowerCase().contains("dcim")) {

						tBitmap = null;
						BitmapFactory.Options opt = new BitmapFactory.Options();
						opt.inSampleSize = 1;
						opt.inJustDecodeBounds = true;
						BitmapFactory.decodeFile(url, opt);
						int bitmapSize = opt.outHeight * opt.outWidth * 4;
						opt.inSampleSize = bitmapSize / (1000 * 2000);
						opt.inJustDecodeBounds = false;
						tBitmap = BitmapFactory.decodeFile(url, opt);
						if (imageRef.width != 0 && imageRef.height != 0) {
							// 缩略图
							bitmap = ThumbnailUtils.extractThumbnail(tBitmap,
									imageRef.width, imageRef.height,
									ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
							isFromNet = true;
						} else {
							bitmap = tBitmap;
							tBitmap = null;
						}

					} else
						bitmap = mDiskCache.get(url);

					if (bitmap != null) {
						// ToolUtil.log("从disk缓存读取");
						// 写入map缓存
						if (imageRef.width != 0 && imageRef.height != 0) {
							if (mMemoryCache.get(url + imageRef.width
									+ imageRef.height) == null)
								mMemoryCache.put(url + imageRef.width
										+ imageRef.height, bitmap);
						} else {
							if (mMemoryCache.get(url) == null)
								mMemoryCache.put(url, bitmap);
						}

					} else {
						try {
							byte[] data = loadByteArrayFromNetwork(url);

							if (data != null) {

								BitmapFactory.Options opt = new BitmapFactory.Options();
								opt.inSampleSize = 1;

								opt.inJustDecodeBounds = true;
								BitmapFactory.decodeByteArray(data, 0,
										data.length, opt);
								int bitmapSize = opt.outHeight * opt.outWidth
										* 4;// pixels*3 if it's RGB and pixels*4
											// if it's ARGB
								if (bitmapSize > 1000 * 1200)
									opt.inSampleSize = 2;
								opt.inJustDecodeBounds = false;
								tBitmap = BitmapFactory.decodeByteArray(data,
										0, data.length, opt);
								if (imageRef.width != 0 && imageRef.height != 0) {
									bitmap = ThumbnailUtils
											.extractThumbnail(
													tBitmap,
													imageRef.width,
													imageRef.height,
													ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
								} else {
									bitmap = tBitmap;
									tBitmap = null;
								}

								if (bitmap != null && url != null) {
									// 写入SD卡
									if (imageRef.width != 0
											&& imageRef.height != 0) {
										mDiskCache.put(url + imageRef.width
												+ imageRef.height, bitmap);
										mMemoryCache.put(url + imageRef.width
												+ imageRef.height, bitmap);
									} else {
										mDiskCache.put(url, bitmap);
										mMemoryCache.put(url, bitmap);
									}
									isFromNet = true;
								}
							}
						} catch (OutOfMemoryError e) {
						}

					}

				}

				if (mImageManagerHandler != null) {
					Message message = mImageManagerHandler.obtainMessage(
							MSG_REPLY, bitmap);
					mImageManagerHandler.sendMessage(message);
				}
				break;

			case MSG_REFRESH_ONE:
				Bitmap bitmap1 = null;
				Bitmap tBitmap1 = null;
				if (msg.obj != null && msg.obj instanceof ImageRef) {

					ImageRef imageRef = (ImageRef) msg.obj;
					String url = imageRef.url;
					if (url == null)
						return;
					// 如果本地url即读取sd相册图片，则直接读取，不用经过DiskCache
					if (url.toLowerCase().contains("dcim")) {

						tBitmap1 = null;
						BitmapFactory.Options opt = new BitmapFactory.Options();
						opt.inSampleSize = 1;
						opt.inJustDecodeBounds = true;
						BitmapFactory.decodeFile(url, opt);
						int bitmapSize = opt.outHeight * opt.outWidth * 4;
						opt.inSampleSize = bitmapSize / (1000 * 2000);
						opt.inJustDecodeBounds = false;
						tBitmap1 = BitmapFactory.decodeFile(url, opt);
						if (imageRef.width != 0 && imageRef.height != 0) {
							bitmap1 = ThumbnailUtils.extractThumbnail(tBitmap1,
									imageRef.width, imageRef.height,
									ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
							isFromNet = true;
						} else {
							bitmap1 = tBitmap1;
							tBitmap1 = null;
						}

					} else {
						// do nothing
						// bitmap1 = mDiskCache.get(url);
					}

					if (bitmap1 != null) {
						// ToolUtil.log("从disk缓存读取");
						// 写入map缓存
						if (imageRef.width != 0 && imageRef.height != 0) {
							if (mMemoryCache.get(url + imageRef.width
									+ imageRef.height) == null)
								mMemoryCache.put(url + imageRef.width
										+ imageRef.height, bitmap1);
						} else {
							if (mMemoryCache.get(url) == null)
								mMemoryCache.put(url, bitmap1);
						}

					} else {
						try {
							byte[] data = loadByteArrayFromNetwork(url);

							if (data != null) {

								BitmapFactory.Options opt = new BitmapFactory.Options();
								opt.inSampleSize = 1;

								opt.inJustDecodeBounds = true;
								BitmapFactory.decodeByteArray(data, 0,
										data.length, opt);
								int bitmapSize = opt.outHeight * opt.outWidth
										* 4;// pixels*3 if it's RGB and pixels*4
											// if it's ARGB
								if (bitmapSize > 1000 * 1200)
									opt.inSampleSize = 2;
								opt.inJustDecodeBounds = false;
								tBitmap1 = BitmapFactory.decodeByteArray(data,
										0, data.length, opt);
								if (imageRef.width != 0 && imageRef.height != 0) {
									bitmap1 = ThumbnailUtils
											.extractThumbnail(
													tBitmap1,
													imageRef.width,
													imageRef.height,
													ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
								} else {
									bitmap1 = tBitmap1;
									tBitmap1 = null;
								}
								
								

								if (bitmap1 != null && url != null) {
									// 写入SD卡
									if (imageRef.width != 0
											&& imageRef.height != 0) {
										mDiskCache.put(url + imageRef.width
												+ imageRef.height, bitmap1);
										mMemoryCache.put(url + imageRef.width
												+ imageRef.height, bitmap1);
									} else {
										mDiskCache.put(url, bitmap1);
										mMemoryCache.put(url, bitmap1);
									}
									isFromNet = true;
								}
							} else {
								// 如果网络没有获取到。。。则从硬盘中获取
								bitmap1 = mDiskCache.get(url);
							}
						} catch (OutOfMemoryError e) {
						}

					}

				}

				if (mImageManagerHandler != null) {
					Message message = mImageManagerHandler.obtainMessage(
							MSG_REPLY, bitmap1);
					mImageManagerHandler.sendMessage(message);
				}
				break;

			case MSG_STOP: // 收到终止指令
				Looper.myLooper().quit();
				break;

			}
		}
	}

	/** UI线程消息处理器 */
	private Handler mImageManagerHandler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			if (msg != null) {
				switch (msg.what) {

				case MSG_REPLY: // 收到应答

					do {
						ImageRef imageRef = mRequestQueue.remove();

						if (imageRef == null)
							break;

//						if (imageRef.imageView == null
//								|| imageRef.imageView.getTag() == null
//								|| imageRef.url == null)
//							break;

						if (!(msg.obj instanceof Bitmap) || msg.obj == null) {
							break;
						}
						Bitmap bitmap = (Bitmap) msg.obj;

						// 非同一ImageView
//						if (!(imageRef.url).equals((String) imageRef.imageView
//								.getTag())) {
//							break;
//						}

						setImageBitmap(imageRef.itemizedOverlay, bitmap, isFromNet , imageRef.fence);
						isFromNet = false;

					} while (false);

					break;
				}
			}
			// 设置闲置标志
			mImageLoaderIdle = true;

			// 若服务未关闭，则发送下一个请求。
			if (mImageLoaderHandler != null) {
				sendRequest();
			}
		}
	};

	/**
	 * 添加图片显示渐现动画
	 * 
	 */
	private void setImageBitmap(ItemizedOverlay itemizedOverlay, Bitmap bitmap,
			boolean isTran , int fence) {
		if (isTran) {
			final TransitionDrawable td = new TransitionDrawable(
					new Drawable[] {
							new ColorDrawable(android.R.color.transparent),
							new BitmapDrawable(bitmap) });
			td.setCrossFadeEnabled(true);
//			imageView.setImageDrawable(td);
			itemizedOverlay.getItem(fence).setMarker(td);
			td.startTransition(300);
		} else {
//			imageView.setImageBitmap(bitmap);
		}
	}

	/**
	 * 从网络获取图片字节数组
	 * 
	 * @param url
	 * @return
	 */
	private byte[] loadByteArrayFromNetwork(String url) {

		try {

			HttpGet method = new HttpGet(url);
			HttpResponse response = myapp.getHttpClient().execute(method);
			HttpEntity entity = response.getEntity();
			return EntityUtils.toByteArray(entity);

		} catch (Exception e) {
			return null;
		}

	}

	/**
	 * 根据url生成缓存文件完整路径名
	 * 
	 * @param url
	 * @return
	 */
	public String urlToFilePath(String url) {

		// 扩展名位置
		int index = url.lastIndexOf('.');
		if (index == -1) {
			return null;
		}

		StringBuilder filePath = new StringBuilder();

		// 图片存取路径
		filePath.append(myapp.getCacheDir().toString()).append('/');

		// 图片文件名
		filePath.append(MD5.Md5(url)).append(url.substring(index));

		return filePath.toString();
	}

	/**
	 * Activity#onStop后，ListView不会有残余请求。
	 */
	public void stop() {

		// 清空请求队列
		mImageQueue.clear();

	}

}
