content: /*
   * Copyright (c) 2013. wyouflf (wyouflf@gmail.com)
   *
   * 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.lidroid.xutils.bitmap;
  
  import android.app.ActivityManager;
  import android.content.Context;
  import android.text.TextUtils;
  import com.lidroid.xutils.bitmap.core.BitmapCache;
  import com.lidroid.xutils.bitmap.download.DefaultDownloader;
  import com.lidroid.xutils.bitmap.download.Downloader;
  import com.lidroid.xutils.cache.FileNameGenerator;
  import com.lidroid.xutils.task.Priority;
  import com.lidroid.xutils.task.PriorityAsyncTask;
  import com.lidroid.xutils.task.PriorityExecutor;
  import com.lidroid.xutils.util.LogUtils;
  import com.lidroid.xutils.util.OtherUtils;
  
  import java.util.HashMap;
  
  /**
   * Author: wyouflf
   * Date: 13-7-31
   * Time: 下午11:15
   */
  public class BitmapGlobalConfig {
  
      private String diskCachePath;
      public final static int MIN_MEMORY_CACHE_SIZE = 1024 * 1024 * 2; // 2M
      private int memoryCacheSize = 1024 * 1024 * 4; // 4MB
      public final static int MIN_DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10M
      private int diskCacheSize = 1024 * 1024 * 50;  // 50M
  
      private boolean memoryCacheEnabled = true;
      private boolean diskCacheEnabled = true;
  
      private Downloader downloader;
      private BitmapCache bitmapCache;
  
      private final static int DEFAULT_POOL_SIZE = 5;
      private final static PriorityExecutor BITMAP_LOAD_EXECUTOR = new PriorityExecutor(DEFAULT_POOL_SIZE);
      private final static PriorityExecutor DISK_CACHE_EXECUTOR = new PriorityExecutor(2);
  
      private long defaultCacheExpiry = 1000L * 60 * 60 * 24 * 30; // 30 days
      private int defaultConnectTimeout = 1000 * 15; // 15 sec
      private int defaultReadTimeout = 1000 * 15; // 15 sec
  
      private FileNameGenerator fileNameGenerator;
  
      private BitmapCacheListener bitmapCacheListener;
  
      private Context mContext;
      private final static HashMap<String, BitmapGlobalConfig> configMap = new HashMap<String, BitmapGlobalConfig>(1);
  
      /**
       * @param context
       * @param diskCachePath If null, use default appCacheDir+"/xBitmapCache"
       */
      private BitmapGlobalConfig(Context context, String diskCachePath) {
          if (context == null) throw new IllegalArgumentException("context may not be null");
          this.mContext = context;
          this.diskCachePath = diskCachePath;
          initBitmapCache();
      }
  
      public synchronized static BitmapGlobalConfig getInstance(Context context, String diskCachePath) {
  
          if (TextUtils.isEmpty(diskCachePath)) {
              diskCachePath = OtherUtils.getDiskCacheDir(context, "xBitmapCache");
          }
  
          if (configMap.containsKey(diskCachePath)) {
              return configMap.get(diskCachePath);
          } else {
              BitmapGlobalConfig config = new BitmapGlobalConfig(context, diskCachePath);
              configMap.put(diskCachePath, config);
              return config;
          }
      }
  
      private void initBitmapCache() {
          new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_INIT_MEMORY_CACHE);
          new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_INIT_DISK_CACHE);
      }
  
      public String getDiskCachePath() {
          return diskCachePath;
      }
  
      public Downloader getDownloader() {
          if (downloader == null) {
              downloader = new DefaultDownloader();
          }
          downloader.setContext(mContext);
          downloader.setDefaultExpiry(getDefaultCacheExpiry());
          downloader.setDefaultConnectTimeout(getDefaultConnectTimeout());
          downloader.setDefaultReadTimeout(getDefaultReadTimeout());
          return downloader;
      }
  
      public void setDownloader(Downloader downloader) {
          this.downloader = downloader;
      }
  
      public long getDefaultCacheExpiry() {
          return defaultCacheExpiry;
      }
  
      public void setDefaultCacheExpiry(long defaultCacheExpiry) {
          this.defaultCacheExpiry = defaultCacheExpiry;
      }
  
      public int getDefaultConnectTimeout() {
          return defaultConnectTimeout;
      }
  
      public void setDefaultConnectTimeout(int defaultConnectTimeout) {
          this.defaultConnectTimeout = defaultConnectTimeout;
      }
  
      public int getDefaultReadTimeout() {
          return defaultReadTimeout;
      }
  
      public void setDefaultReadTimeout(int defaultReadTimeout) {
          this.defaultReadTimeout = defaultReadTimeout;
      }
  
      public BitmapCache getBitmapCache() {
          if (bitmapCache == null) {
              bitmapCache = new BitmapCache(this);
          }
          return bitmapCache;
      }
  
      public int getMemoryCacheSize() {
          return memoryCacheSize;
      }
  
      public void setMemoryCacheSize(int memoryCacheSize) {
          if (memoryCacheSize >= MIN_MEMORY_CACHE_SIZE) {
              this.memoryCacheSize = memoryCacheSize;
              if (bitmapCache != null) {
                  bitmapCache.setMemoryCacheSize(this.memoryCacheSize);
              }
          } else {
              this.setMemCacheSizePercent(0.3f);// Set default memory cache size.
          }
      }
  
      /**
       * @param percent between 0.05 and 0.8 (inclusive)
       */
      public void setMemCacheSizePercent(float percent) {
          if (percent < 0.05f || percent > 0.8f) {
              throw new IllegalArgumentException("percent must be between 0.05 and 0.8 (inclusive)");
          }
          this.memoryCacheSize = Math.round(percent * getMemoryClass() * 1024 * 1024);
          if (bitmapCache != null) {
              bitmapCache.setMemoryCacheSize(this.memoryCacheSize);
          }
      }
  
      public int getDiskCacheSize() {
          return diskCacheSize;
      }
  
      public void setDiskCacheSize(int diskCacheSize) {
          if (diskCacheSize >= MIN_DISK_CACHE_SIZE) {
              this.diskCacheSize = diskCacheSize;
              if (bitmapCache != null) {
                  bitmapCache.setDiskCacheSize(this.diskCacheSize);
              }
          }
      }
  
      public int getThreadPoolSize() {
          return BitmapGlobalConfig.BITMAP_LOAD_EXECUTOR.getPoolSize();
      }
  
      public void setThreadPoolSize(int threadPoolSize) {
          BitmapGlobalConfig.BITMAP_LOAD_EXECUTOR.setPoolSize(threadPoolSize);
      }
  
      public PriorityExecutor getBitmapLoadExecutor() {
          return BitmapGlobalConfig.BITMAP_LOAD_EXECUTOR;
      }
  
      public PriorityExecutor getDiskCacheExecutor() {
          return BitmapGlobalConfig.DISK_CACHE_EXECUTOR;
      }
  
      public boolean isMemoryCacheEnabled() {
          return memoryCacheEnabled;
      }
  
      public void setMemoryCacheEnabled(boolean memoryCacheEnabled) {
          this.memoryCacheEnabled = memoryCacheEnabled;
      }
  
      public boolean isDiskCacheEnabled() {
          return diskCacheEnabled;
      }
  
      public void setDiskCacheEnabled(boolean diskCacheEnabled) {
          this.diskCacheEnabled = diskCacheEnabled;
      }
  
      public FileNameGenerator getFileNameGenerator() {
          return fileNameGenerator;
      }
  
      public void setFileNameGenerator(FileNameGenerator fileNameGenerator) {
          this.fileNameGenerator = fileNameGenerator;
          if (bitmapCache != null) {
              bitmapCache.setDiskCacheFileNameGenerator(fileNameGenerator);
          }
      }
  
      public BitmapCacheListener getBitmapCacheListener() {
          return bitmapCacheListener;
      }
  
      public void setBitmapCacheListener(BitmapCacheListener bitmapCacheListener) {
          this.bitmapCacheListener = bitmapCacheListener;
      }
  
      private int getMemoryClass() {
          return ((ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
      }
  
      ////////////////////////////////// bitmap cache management task ///////////////////////////////////////
      private class BitmapCacheManagementTask extends PriorityAsyncTask<Object, Void, Object[]> {
          public static final int MESSAGE_INIT_MEMORY_CACHE = 0;
          public static final int MESSAGE_INIT_DISK_CACHE = 1;
          public static final int MESSAGE_FLUSH = 2;
          public static final int MESSAGE_CLOSE = 3;
          public static final int MESSAGE_CLEAR = 4;
          public static final int MESSAGE_CLEAR_MEMORY = 5;
          public static final int MESSAGE_CLEAR_DISK = 6;
          public static final int MESSAGE_CLEAR_BY_KEY = 7;
          public static final int MESSAGE_CLEAR_MEMORY_BY_KEY = 8;
          public static final int MESSAGE_CLEAR_DISK_BY_KEY = 9;
  
          private BitmapCacheManagementTask() {
              this.setPriority(Priority.UI_TOP);
          }
  
          @Override
          protected Object[] doInBackground(Object... params) {
              if (params == null || params.length == 0) return params;
              BitmapCache cache = getBitmapCache();
              if (cache == null) return params;
              try {
                  switch ((Integer) params[0]) {
                      case MESSAGE_INIT_MEMORY_CACHE:
                          cache.initMemoryCache();
                          break;
                      case MESSAGE_INIT_DISK_CACHE:
                          cache.initDiskCache();
                          break;
                      case MESSAGE_FLUSH:
                          cache.flush();
                          break;
                      case MESSAGE_CLOSE:
                          cache.clearMemoryCache();
                          cache.close();
                          break;
                      case MESSAGE_CLEAR:
                          cache.clearCache();
                          break;
                      case MESSAGE_CLEAR_MEMORY:
                          cache.clearMemoryCache();
                          break;
                      case MESSAGE_CLEAR_DISK:
                          cache.clearDiskCache();
                          break;
                      case MESSAGE_CLEAR_BY_KEY:
                          if (params.length != 2) return params;
                          cache.clearCache(String.valueOf(params[1]));
                          break;
                      case MESSAGE_CLEAR_MEMORY_BY_KEY:
                          if (params.length != 2) return params;
                          cache.clearMemoryCache(String.valueOf(params[1]));
                          break;
                      case MESSAGE_CLEAR_DISK_BY_KEY:
                          if (params.length != 2) return params;
                          cache.clearDiskCache(String.valueOf(params[1]));
                          break;
                      default:
                          break;
                  }
              } catch (Throwable e) {
                  LogUtils.e(e.getMessage(), e);
              }
              return params;
          }
  
          @Override
          protected void onPostExecute(Object[] params) {
              if (bitmapCacheListener == null || params == null || params.length == 0) return;
              try {
                  switch ((Integer) params[0]) {
                      case MESSAGE_INIT_MEMORY_CACHE:
                          bitmapCacheListener.onInitMemoryCacheFinished();
                          break;
                      case MESSAGE_INIT_DISK_CACHE:
                          bitmapCacheListener.onInitDiskFinished();
                          break;
                      case MESSAGE_FLUSH:
                          bitmapCacheListener.onFlushCacheFinished();
                          break;
                      case MESSAGE_CLOSE:
                          bitmapCacheListener.onCloseCacheFinished();
                          break;
                      case MESSAGE_CLEAR:
                          bitmapCacheListener.onClearCacheFinished();
                          break;
                      case MESSAGE_CLEAR_MEMORY:
                          bitmapCacheListener.onClearMemoryCacheFinished();
                          break;
                      case MESSAGE_CLEAR_DISK:
                          bitmapCacheListener.onClearDiskCacheFinished();
                          break;
                      case MESSAGE_CLEAR_BY_KEY:
                          if (params.length != 2) return;
                          bitmapCacheListener.onClearCacheFinished(String.valueOf(params[1]));
                          break;
                      case MESSAGE_CLEAR_MEMORY_BY_KEY:
                          if (params.length != 2) return;
                          bitmapCacheListener.onClearMemoryCacheFinished(String.valueOf(params[1]));
                          break;
                      case MESSAGE_CLEAR_DISK_BY_KEY:
                          if (params.length != 2) return;
                          bitmapCacheListener.onClearDiskCacheFinished(String.valueOf(params[1]));
                          break;
                      default:
                          break;
                  }
              } catch (Throwable e) {
                  LogUtils.e(e.getMessage(), e);
              }
          }
      }
  
      public void clearCache() {
          new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_CLEAR);
      }
  
      public void clearMemoryCache() {
          new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_CLEAR_MEMORY);
      }
  
      public void clearDiskCache() {
          new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_CLEAR_DISK);
      }
  
      public void clearCache(String uri) {
          new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_CLEAR_BY_KEY, uri);
      }
  
      public void clearMemoryCache(String uri) {
          new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_CLEAR_MEMORY_BY_KEY, uri);
      }
  
      public void clearDiskCache(String uri) {
          new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_CLEAR_DISK_BY_KEY, uri);
      }
  
      public void flushCache() {
          new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_FLUSH);
      }
  
      public void closeCache() {
          new BitmapCacheManagementTask().execute(BitmapCacheManagementTask.MESSAGE_CLOSE);
      }
  }