/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * 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.android.mms.util;

import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Set;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.util.Log;

import com.android.mms.LogTag;
import com.android.mms.R;
import com.android.mms.TempFileProvider;
import com.android.mms.ui.UriImage;
import com.android.mms.util.ImageCacheService.ImageData;

/**
 * Primary {@link ThumbnailManager} implementation used by {@link MessagingApplication}.
 * <p>
 * Public methods should only be used from a single thread (typically the UI
 * thread). Callbacks will be invoked on the thread where the ThumbnailManager
 * was instantiated.
 * <p>
 * Uses a thread-pool ExecutorService instead of AsyncTasks since clients may
 * request lots of pdus around the same time, and AsyncTask may reject tasks
 * in that case and has no way of bounding the number of threads used by those
 * tasks.
 * <p>
 * ThumbnailManager is used to asynchronously load pictures and create thumbnails. The thumbnails
 * are stored in a local cache with SoftReferences. Once a thumbnail is loaded, it will call the
 * passed in callback with the result. If a thumbnail is immediately available in the cache,
 * the callback will be called immediately as well.
 *
 * Based on BooksImageManager by Virgil King.
 */
public class ThumbnailManager extends BackgroundLoaderManager {
    private static final String TAG = "ThumbnailManager";

    private static final boolean DEBUG_DISABLE_CACHE = false;
    private static final boolean DEBUG_DISABLE_CALLBACK = false;
    private static final boolean DEBUG_DISABLE_LOAD = false;
    private static final boolean DEBUG_LONG_WAIT = false;

    private static final int COMPRESS_JPEG_QUALITY = 90;

    private final SimpleCache<Uri, Bitmap> mThumbnailCache;
    private final Context mContext;
    private ImageCacheService mImageCacheService;
    private static Bitmap mEmptyImageBitmap;
    private static Bitmap mEmptyVideoBitmap;

    // NOTE: These type numbers are stored in the image cache, so it should not
    // not be changed without resetting the cache.
    public static final int TYPE_THUMBNAIL = 1;
    public static final int TYPE_MICROTHUMBNAIL = 2;

    public static final int THUMBNAIL_TARGET_SIZE = 640;

    public ThumbnailManager(final Context context) {
        super(context);

        mThumbnailCache = new SimpleCache<Uri, Bitmap>(8, 16, 0.75f, true);
        mContext = context;

        mEmptyImageBitmap = BitmapFactory.decodeResource(context.getResources(),
                R.drawable.ic_missing_thumbnail_picture);

        mEmptyVideoBitmap = BitmapFactory.decodeResource(context.getResources(),
                R.drawable.ic_missing_thumbnail_video);
    }

    /**
     * getThumbnail must be called on the same thread that created ThumbnailManager. This is
     * normally the UI thread.
     * @param uri the uri of the image
     * @param width the original full width of the image
     * @param height the original full height of the image
     * @param callback the callback to call when the thumbnail is fully loaded
     * @return
     */
    public ItemLoadedFuture getThumbnail(Uri uri,
            final ItemLoadedCallback<ImageLoaded> callback) {
        return getThumbnail(uri, false, callback);
    }

    /**
     * getVideoThumbnail must be called on the same thread that created ThumbnailManager. This is
     * normally the UI thread.
     * @param uri the uri of the image
     * @param callback the callback to call when the thumbnail is fully loaded
     * @return
     */
    public ItemLoadedFuture getVideoThumbnail(Uri uri,
            final ItemLoadedCallback<ImageLoaded> callback) {
        return getThumbnail(uri, true, callback);
    }

    private ItemLoadedFuture getThumbnail(Uri uri, boolean isVideo,
            final ItemLoadedCallback<ImageLoaded> callback) {
        if (uri == null) {
            throw new NullPointerException();
        }

        final Bitmap thumbnail = DEBUG_DISABLE_CACHE ? null : mThumbnailCache.get(uri);

        final boolean thumbnailExists = (thumbnail != null);
        final boolean taskExists = mPendingTaskUris.contains(uri);
        final boolean newTaskRequired = !thumbnailExists && !taskExists;
        final boolean callbackRequired = (callback != null);

        if (Log.isLoggable(LogTag.THUMBNAIL_CACHE, Log.DEBUG)) {
            Log.v(TAG, "getThumbnail mThumbnailCache.get for uri: " + uri + " thumbnail: " +
                    thumbnail + " callback: " + callback + " thumbnailExists: " +
                    thumbnailExists + " taskExists: " + taskExists +
                    " newTaskRequired: " + newTaskRequired +
                    " callbackRequired: " + callbackRequired);
        }

        if (thumbnailExists) {
            if (callbackRequired && !DEBUG_DISABLE_CALLBACK) {
                ImageLoaded imageLoaded = new ImageLoaded(thumbnail, isVideo);
                callback.onItemLoaded(imageLoaded, null);
            }
            return new NullItemLoadedFuture();
        }

        if (callbackRequired) {
            addCallback(uri, callback);
        }

        if (newTaskRequired) {
            mPendingTaskUris.add(uri);
            Runnable task = new ThumbnailTask(uri, isVideo);
            mExecutor.execute(task);
        }
        return new ItemLoadedFuture() {
            private boolean mIsDone;

            @Override
            public void cancel(Uri uri) {
                cancelCallback(callback);
                removeThumbnail(uri);   // if the thumbnail is half loaded, force a reload next time
            }

            @Override
            public void setIsDone(boolean done) {
                mIsDone = done;
            }

            @Override
            public boolean isDone() {
                return mIsDone;
            }
        };
    }

    @Override
    public synchronized void clear() {
        super.clear();

        mThumbnailCache.clear();    // clear in-memory cache
        clearBackingStore();        // clear on-disk cache
    }

    // Delete the on-disk cache, but leave the in-memory cache intact
    public synchronized void clearBackingStore() {
        if (mImageCacheService == null) {
            // No need to call getImageCacheService() to renew the instance if it's null.
            // It's enough to only delete the image cache files for the sake of safety.
            CacheManager.clear(mContext);
        } else {
            getImageCacheService().clear();

            // force a re-init the next time getImageCacheService requested
            mImageCacheService = null;
        }
    }

    public void removeThumbnail(Uri uri) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "removeThumbnail: " + uri);
        }
        if (uri != null) {
            mThumbnailCache.remove(uri);
        }
    }

    @Override
    public String getTag() {
        return TAG;
    }

    private synchronized ImageCacheService getImageCacheService() {
        if (mImageCacheService == null) {
            mImageCacheService = new ImageCacheService(mContext);
        }
        return mImageCacheService;
    }

    public class ThumbnailTask implements Runnable {
        private final Uri mUri;
        private final boolean mIsVideo;

        public ThumbnailTask(Uri uri, boolean isVideo) {
            if (uri == null) {
                throw new NullPointerException();
            }
            mUri = uri;
            mIsVideo = isVideo;
        }

        /** {@inheritDoc} */
        @Override
        public void run() {
            if (DEBUG_DISABLE_LOAD) {
                return;
            }
            if (DEBUG_LONG_WAIT) {
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                }
            }

            Bitmap bitmap = null;
            try {
                bitmap = getBitmap(mIsVideo);
            } catch (IllegalArgumentException e) {
                Log.e(TAG, "Couldn't load bitmap for " + mUri, e);
            } catch (OutOfMemoryError e) {
                Log.e(TAG, "Couldn't load bitmap for " + mUri, e);
            }
            final Bitmap resultBitmap = bitmap;

            mCallbackHandler.post(new Runnable() {
                @Override
                public void run() {
                    final Set<ItemLoadedCallback> callbacks = mCallbacks.get(mUri);
                    if (callbacks != null) {
                        Bitmap bitmap = resultBitmap == null ?
                                (mIsVideo ? mEmptyVideoBitmap : mEmptyImageBitmap)
                                : resultBitmap;

                        // Make a copy so that the callback can unregister itself
                        for (final ItemLoadedCallback<ImageLoaded> callback : asList(callbacks)) {
                            if (Log.isLoggable(LogTag.THUMBNAIL_CACHE, Log.DEBUG)) {
                                Log.d(TAG, "Invoking item loaded callback " + callback);
                            }
                            if (!DEBUG_DISABLE_CALLBACK) {
                                ImageLoaded imageLoaded = new ImageLoaded(bitmap, mIsVideo);
                                callback.onItemLoaded(imageLoaded, null);
                            }
                        }
                    } else {
                        if (Log.isLoggable(TAG, Log.DEBUG)) {
                            Log.d(TAG, "No image callback!");
                        }
                    }

                    // Add the bitmap to the soft cache if the load succeeded. Don't cache the
                    // stand-ins for empty bitmaps.
                    if (resultBitmap != null) {
                        mThumbnailCache.put(mUri, resultBitmap);
                        if (Log.isLoggable(LogTag.THUMBNAIL_CACHE, Log.DEBUG)) {
                            Log.v(TAG, "in callback runnable: bitmap uri: " + mUri +
                                    " width: " + resultBitmap.getWidth() + " height: " +
                                    resultBitmap.getHeight() + " size: " +
                                    resultBitmap.getByteCount());
                        }
                    }

                    mCallbacks.remove(mUri);
                    mPendingTaskUris.remove(mUri);

                    if (Log.isLoggable(LogTag.THUMBNAIL_CACHE, Log.DEBUG)) {
                        Log.d(TAG, "Image task for " + mUri + "exiting " + mPendingTaskUris.size()
                                + " remain");
                    }
                }
            });
        }

        private Bitmap getBitmap(boolean isVideo) {
            ImageCacheService cacheService = getImageCacheService();

            UriImage uriImage = new UriImage(mContext, mUri);
            String path = uriImage.getPath();

            if (path == null) {
                return null;
            }

            // We never want to store thumbnails of temp files in the thumbnail cache on disk
            // because those temp filenames are recycled (and reused when capturing images
            // or videos).
            boolean isTempFile = TempFileProvider.isTempFile(path);

            ImageData data = null;
            if (!isTempFile) {
                data = cacheService.getImageData(path, TYPE_THUMBNAIL);
            }

            if (data != null) {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                Bitmap bitmap = requestDecode(data.mData,
                        data.mOffset, data.mData.length - data.mOffset, options);
                if (bitmap == null) {
                    Log.w(TAG, "decode cached failed " + path);
                }
                return bitmap;
            } else {
                Bitmap bitmap;
                if (isVideo) {
                    bitmap = getVideoBitmap();
                } else {
                    bitmap = onDecodeOriginal(mUri, TYPE_THUMBNAIL);
                }
                if (bitmap == null) {
                    Log.w(TAG, "decode orig failed " + path);
                    return null;
                }

                bitmap = resizeDownBySideLength(bitmap, THUMBNAIL_TARGET_SIZE, true);

                if (!isTempFile) {
                    byte[] array = compressBitmap(bitmap);
                    cacheService.putImageData(path, TYPE_THUMBNAIL, array);
                }
                return bitmap;
            }
        }

        private Bitmap getVideoBitmap() {
            MediaMetadataRetriever retriever = new MediaMetadataRetriever();
            try {
                retriever.setDataSource(mContext, mUri);
                return retriever.getFrameAtTime(-1);
            } catch (RuntimeException ex) {
                // Assume this is a corrupt video file.
            } finally {
                try {
                    retriever.release();
                } catch (RuntimeException ex) {
                    // Ignore failures while cleaning up.
                }
            }
            return null;
        }

        private byte[] compressBitmap(Bitmap bitmap) {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG,
                    COMPRESS_JPEG_QUALITY, os);
            return os.toByteArray();
        }

        private Bitmap requestDecode(byte[] bytes, int offset,
                int length, Options options) {
            if (options == null) {
                options = new Options();
            }
            return ensureGLCompatibleBitmap(
                    BitmapFactory.decodeByteArray(bytes, offset, length, options));
        }

        private Bitmap resizeDownBySideLength(
                Bitmap bitmap, int maxLength, boolean recycle) {
            int srcWidth = bitmap.getWidth();
            int srcHeight = bitmap.getHeight();
            float scale = Math.min(
                    (float) maxLength / srcWidth, (float) maxLength / srcHeight);
            if (scale >= 1.0f) return bitmap;
            return resizeBitmapByScale(bitmap, scale, recycle);
        }

        private Bitmap resizeBitmapByScale(
                Bitmap bitmap, float scale, boolean recycle) {
            int width = Math.round(bitmap.getWidth() * scale);
            int height = Math.round(bitmap.getHeight() * scale);
            if (width == bitmap.getWidth()
                    && height == bitmap.getHeight()) return bitmap;
            Bitmap target = Bitmap.createBitmap(width, height, getConfig(bitmap));
            Canvas canvas = new Canvas(target);
            canvas.scale(scale, scale);
            Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
            canvas.drawBitmap(bitmap, 0, 0, paint);
            if (recycle) bitmap.recycle();
            return target;
        }

        private Bitmap.Config getConfig(Bitmap bitmap) {
            Bitmap.Config config = bitmap.getConfig();
            if (config == null) {
                config = Bitmap.Config.ARGB_8888;
            }
            return config;
        }

        // TODO: This function should not be called directly from
        // DecodeUtils.requestDecode(...), since we don't have the knowledge
        // if the bitmap will be uploaded to GL.
        private Bitmap ensureGLCompatibleBitmap(Bitmap bitmap) {
            if (bitmap == null || bitmap.getConfig() != null) return bitmap;
            Bitmap newBitmap = bitmap.copy(Config.ARGB_8888, false);
            bitmap.recycle();
            return newBitmap;
        }

        private Bitmap onDecodeOriginal(Uri uri, int type) {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inPreferredConfig = Bitmap.Config.ARGB_8888;

            return requestDecode(uri, options, THUMBNAIL_TARGET_SIZE);
        }

        private void closeSilently(Closeable c) {
            if (c == null) return;
            try {
                c.close();
            } catch (Throwable t) {
                Log.w(TAG, "close fail", t);
            }
        }

        private Bitmap requestDecode(final Uri uri, Options options, int targetSize) {
            if (options == null) options = new Options();

            InputStream inputStream;
            try {
                inputStream = mContext.getContentResolver().openInputStream(uri);
            } catch (FileNotFoundException e) {
                Log.e(TAG, "Can't open uri: " + uri, e);
                return null;
            }

            options.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(inputStream, null, options);
            closeSilently(inputStream);

            // No way to reset the stream. Have to open it again :-(
            try {
                inputStream = mContext.getContentResolver().openInputStream(uri);
            } catch (FileNotFoundException e) {
                Log.e(TAG, "Can't open uri: " + uri, e);
                return null;
            }

            options.inSampleSize = computeSampleSizeLarger(
                    options.outWidth, options.outHeight, targetSize);
            options.inJustDecodeBounds = false;

            Bitmap result = BitmapFactory.decodeStream(inputStream, null, options);
            closeSilently(inputStream);

            if (result == null) {
                return null;
            }

            // We need to resize down if the decoder does not support inSampleSize.
            // (For example, GIF images.)
            result = resizeDownIfTooBig(result, targetSize, true);
            return ensureGLCompatibleBitmap(result);
        }

        // This computes a sample size which makes the longer side at least
        // minSideLength long. If that's not possible, return 1.
        private int computeSampleSizeLarger(int w, int h,
                int minSideLength) {
            int initialSize = Math.max(w / minSideLength, h / minSideLength);
            if (initialSize <= 1) return 1;

            return initialSize <= 8
                    ? prevPowerOf2(initialSize)
                    : initialSize / 8 * 8;
        }

        // Returns the previous power of two.
        // Returns the input if it is already power of 2.
        // Throws IllegalArgumentException if the input is <= 0
        private int prevPowerOf2(int n) {
            if (n <= 0) throw new IllegalArgumentException();
            return Integer.highestOneBit(n);
        }

        // Resize the bitmap if each side is >= targetSize * 2
        private Bitmap resizeDownIfTooBig(
                Bitmap bitmap, int targetSize, boolean recycle) {
            int srcWidth = bitmap.getWidth();
            int srcHeight = bitmap.getHeight();
            float scale = Math.max(
                    (float) targetSize / srcWidth, (float) targetSize / srcHeight);
            if (scale > 0.5f) return bitmap;
            return resizeBitmapByScale(bitmap, scale, recycle);
        }

    }

    public static class ImageLoaded {
        public final Bitmap mBitmap;
        public final boolean mIsVideo;

        public ImageLoaded(Bitmap bitmap, boolean isVideo) {
            mBitmap = bitmap;
            mIsVideo = isVideo;
        }
    }
}
