/*
 * Copyright (C) 2013 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.bitmap;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Rect;
import android.os.AsyncTask;
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor.AutoCloseInputStream;
import android.util.Log;

import com.android.bitmap.RequestKey.FileDescriptorFactory;
import com.android.bitmap.util.BitmapUtils;
import com.android.bitmap.util.Exif;
import com.android.bitmap.util.RectUtils;
import com.android.bitmap.util.Trace;

import java.io.IOException;
import java.io.InputStream;

/**
 * Decodes an image from either a file descriptor or input stream on a worker thread. After the
 * decode is complete, even if the task is cancelled, the result is placed in the given cache.
 * A {@link DecodeCallback} client may be notified on decode begin and completion.
 * <p>
 * This class uses {@link BitmapRegionDecoder} when possible to minimize unnecessary decoding
 * and allow bitmap reuse on Jellybean 4.1 and later.
 * <p>
 *  GIFs are supported, but their decode does not reuse bitmaps at all. The resulting
 *  {@link ReusableBitmap} will be marked as not reusable
 *  ({@link ReusableBitmap#isEligibleForPooling()} will return false).
 */
public class DecodeTask extends AsyncTask<Void, Void, ReusableBitmap> {

    private final RequestKey mKey;
    private final DecodeOptions mDecodeOpts;
    private final FileDescriptorFactory mFactory;
    private final DecodeCallback mDecodeCallback;
    private final BitmapCache mCache;
    private final BitmapFactory.Options mOpts = new BitmapFactory.Options();

    private ReusableBitmap mInBitmap = null;

    private static final boolean CROP_DURING_DECODE = true;

    private static final String TAG = DecodeTask.class.getSimpleName();
    public static final boolean DEBUG = false;

    /**
     * Callback interface for clients to be notified of decode state changes and completion.
     */
    public interface DecodeCallback {
        /**
         * Notifies that the async task's work is about to begin. Up until this point, the task
         * may have been preempted by the scheduler or queued up by a bottlenecked executor.
         * <p>
         * N.B. this method runs on the UI thread.
         */
        void onDecodeBegin(RequestKey key);
        /**
         * The task is now complete and the ReusableBitmap is available for use. Clients should
         * double check that the request matches what the client is expecting.
         */
        void onDecodeComplete(RequestKey key, ReusableBitmap result);
        /**
         * The task has been canceled, and {@link #onDecodeComplete(RequestKey, ReusableBitmap)}
         * will not be called.
         */
        void onDecodeCancel(RequestKey key);
    }

    /**
   * Create new DecodeTask.
   *
   * @param requestKey The request to decode, also the key to use for the cache.
   * @param decodeOpts The decode options.
   * @param factory    The factory to obtain file descriptors to decode from. If this factory is
     *                 null, then we will decode from requestKey.createInputStream().
   * @param callback   The callback to notify of decode state changes.
   * @param cache      The cache and pool.
   */
    public DecodeTask(RequestKey requestKey, DecodeOptions decodeOpts,
            FileDescriptorFactory factory, DecodeCallback callback, BitmapCache cache) {
        mKey = requestKey;
        mDecodeOpts = decodeOpts;
        mFactory = factory;
        mDecodeCallback = callback;
        mCache = cache;
    }

    @Override
    protected ReusableBitmap doInBackground(Void... params) {
        // enqueue the 'onDecodeBegin' signal on the main thread
        publishProgress();

        return decode();
    }

    public ReusableBitmap decode() {
        if (isCancelled()) {
            return null;
        }

        ReusableBitmap result = null;
        ParcelFileDescriptor fd = null;
        InputStream in = null;

        try {
            if (mFactory != null) {
                Trace.beginSection("create fd");
                fd = mFactory.createFileDescriptor();
                Trace.endSection();
            } else {
                in = reset(in);
                if (in == null) {
                    return null;
                }
                if (isCancelled()) {
                    return null;
                }
            }

            final boolean isJellyBeanOrAbove = android.os.Build.VERSION.SDK_INT
                    >= android.os.Build.VERSION_CODES.JELLY_BEAN;
            // This blocks during fling when the pool is empty. We block early to avoid jank.
            if (isJellyBeanOrAbove) {
                Trace.beginSection("poll for reusable bitmap");
                mInBitmap = mCache.poll();
                Trace.endSection();
            }

            if (isCancelled()) {
                return null;
            }

            Trace.beginSection("get bytesize");
            final long byteSize;
            if (fd != null) {
                byteSize = fd.getStatSize();
            } else {
                byteSize = -1;
            }
            Trace.endSection();

            Trace.beginSection("get orientation");
            final int orientation;
            if (mKey.hasOrientationExif()) {
                if (fd != null) {
                    // Creating an input stream from the file descriptor makes it useless
                    // afterwards.
                    Trace.beginSection("create orientation fd and stream");
                    final ParcelFileDescriptor orientationFd = mFactory.createFileDescriptor();
                    in = new AutoCloseInputStream(orientationFd);
                    Trace.endSection();
                }
                orientation = Exif.getOrientation(in, byteSize);
                if (fd != null) {
                    try {
                        // Close the temporary file descriptor.
                        in.close();
                    } catch (IOException ignored) {
                    }
                }
            } else {
                orientation = 0;
            }
            final boolean isNotRotatedOr180 = orientation == 0 || orientation == 180;
            Trace.endSection();

            if (orientation != 0) {
                // disable inBitmap-- bitmap reuse doesn't work with different decode regions due
                // to orientation
                if (mInBitmap != null) {
                    mCache.offer(mInBitmap);
                    mInBitmap = null;
                    mOpts.inBitmap = null;
                }
            }

            if (isCancelled()) {
                return null;
            }

            if (fd == null) {
                in = reset(in);
                if (in == null) {
                    return null;
                }
                if (isCancelled()) {
                    return null;
                }
            }

            Trace.beginSection("decodeBounds");
            mOpts.inJustDecodeBounds = true;
            if (fd != null) {
                BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor(), null, mOpts);
            } else {
                BitmapFactory.decodeStream(in, null, mOpts);
            }
            Trace.endSection();

            if (isCancelled()) {
                return null;
            }

            // We want to calculate the sample size "as if" the orientation has been corrected.
            final int srcW, srcH; // Orientation corrected.
            if (isNotRotatedOr180) {
                srcW = mOpts.outWidth;
                srcH = mOpts.outHeight;
            } else {
                srcW = mOpts.outHeight;
                srcH = mOpts.outWidth;
            }

            // BEGIN MANUAL-INLINE calculateSampleSize()

            final float sz = Math
                    .min((float) srcW / mDecodeOpts.destW, (float) srcH / mDecodeOpts.destH);

            final int sampleSize;
            switch (mDecodeOpts.sampleSizeStrategy) {
                case DecodeOptions.STRATEGY_TRUNCATE:
                    sampleSize = (int) sz;
                    break;
                case DecodeOptions.STRATEGY_ROUND_UP:
                    sampleSize = (int) Math.ceil(sz);
                    break;
                case DecodeOptions.STRATEGY_ROUND_NEAREST:
                default:
                    sampleSize = (int) Math.pow(2, (int) (0.5 + (Math.log(sz) / Math.log(2))));
                    break;
            }
            mOpts.inSampleSize = Math.max(1, sampleSize);

            // END MANUAL-INLINE calculateSampleSize()

            mOpts.inJustDecodeBounds = false;
            mOpts.inMutable = true;
            if (isJellyBeanOrAbove && orientation == 0) {
                if (mInBitmap == null) {
                    if (DEBUG) {
                        Log.e(TAG, "decode thread wants a bitmap. cache dump:\n"
                                + mCache.toDebugString());
                    }
                    Trace.beginSection("create reusable bitmap");
                    mInBitmap = new ReusableBitmap(
                            Bitmap.createBitmap(mDecodeOpts.destW, mDecodeOpts.destH,
                                    Bitmap.Config.ARGB_8888));
                    Trace.endSection();

                    if (isCancelled()) {
                        return null;
                    }

                    if (DEBUG) {
                        Log.e(TAG, "*** allocated new bitmap in decode thread: "
                                + mInBitmap + " key=" + mKey);
                    }
                } else {
                    if (DEBUG) {
                        Log.e(TAG, "*** reusing existing bitmap in decode thread: "
                                + mInBitmap + " key=" + mKey);
                    }

                }
                mOpts.inBitmap = mInBitmap.bmp;
            }

            if (isCancelled()) {
                return null;
            }

            if (fd == null) {
                in = reset(in);
                if (in == null) {
                    return null;
                }
                if (isCancelled()) {
                    return null;
                }
            }


            Bitmap decodeResult = null;
            final Rect srcRect = new Rect(); // Not orientation corrected. True coordinates.
            if (CROP_DURING_DECODE) {
                try {
                    Trace.beginSection("decodeCropped" + mOpts.inSampleSize);

                    // BEGIN MANUAL INLINE decodeCropped()

                    final BitmapRegionDecoder brd;
                    if (fd != null) {
                        brd = BitmapRegionDecoder
                                .newInstance(fd.getFileDescriptor(), true /* shareable */);
                    } else {
                        brd = BitmapRegionDecoder.newInstance(in, true /* shareable */);
                    }

                    final Bitmap bitmap;
                    if (isCancelled()) {
                        bitmap = null;
                    } else {
                        // We want to call calculateCroppedSrcRect() on the source rectangle "as
                        // if" the orientation has been corrected.
                        // Center the decode on the top 1/3.
                        BitmapUtils.calculateCroppedSrcRect(srcW, srcH, mDecodeOpts.destW,
                                mDecodeOpts.destH,
                                mDecodeOpts.destH, mOpts.inSampleSize, mDecodeOpts.verticalCenter,
                                true /* absoluteFraction */,
                                1f, srcRect);
                        if (DEBUG) {
                            System.out.println("rect for this decode is: " + srcRect
                                    + " srcW/H=" + srcW + "/" + srcH
                                    + " dstW/H=" + mDecodeOpts.destW + "/" + mDecodeOpts.destH);
                        }

                        // calculateCroppedSrcRect() gave us the source rectangle "as if" the
                        // orientation has been corrected. We need to decode the uncorrected
                        // source rectangle. Calculate true coordinates.
                        RectUtils.rotateRectForOrientation(orientation, new Rect(0, 0, srcW, srcH),
                                srcRect);

                        bitmap = brd.decodeRegion(srcRect, mOpts);
                    }
                    brd.recycle();

                    // END MANUAL INLINE decodeCropped()

                    decodeResult = bitmap;
                } catch (IOException e) {
                    // fall through to below and try again with the non-cropping decoder
                    if (fd == null) {
                        in = reset(in);
                        if (in == null) {
                            return null;
                        }
                        if (isCancelled()) {
                            return null;
                        }
                    }

                    e.printStackTrace();
                } finally {
                    Trace.endSection();
                }

                if (isCancelled()) {
                    return null;
                }
            }

            //noinspection PointlessBooleanExpression
            if (!CROP_DURING_DECODE || (decodeResult == null && !isCancelled())) {
                try {
                    Trace.beginSection("decode" + mOpts.inSampleSize);
                    // disable inBitmap-- bitmap reuse doesn't work well below K
                    if (mInBitmap != null) {
                        mCache.offer(mInBitmap);
                        mInBitmap = null;
                        mOpts.inBitmap = null;
                    }
                    decodeResult = decode(fd, in);
                } catch (IllegalArgumentException e) {
                    Log.e(TAG, "decode failed: reason='" + e.getMessage() + "' ss="
                            + mOpts.inSampleSize);

                    if (mOpts.inSampleSize > 1) {
                        // try again with ss=1
                        mOpts.inSampleSize = 1;
                        decodeResult = decode(fd, in);
                    }
                } finally {
                    Trace.endSection();
                }

                if (isCancelled()) {
                    return null;
                }
            }

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

            if (mInBitmap != null) {
                result = mInBitmap;
                // srcRect is non-empty when using the cropping BitmapRegionDecoder codepath
                if (!srcRect.isEmpty()) {
                    result.setLogicalWidth((srcRect.right - srcRect.left) / mOpts.inSampleSize);
                    result.setLogicalHeight(
                            (srcRect.bottom - srcRect.top) / mOpts.inSampleSize);
                } else {
                    result.setLogicalWidth(mOpts.outWidth);
                    result.setLogicalHeight(mOpts.outHeight);
                }
            } else {
                // no mInBitmap means no pooling
                result = new ReusableBitmap(decodeResult, false /* reusable */);
                if (isNotRotatedOr180) {
                    result.setLogicalWidth(decodeResult.getWidth());
                    result.setLogicalHeight(decodeResult.getHeight());
                } else {
                    result.setLogicalWidth(decodeResult.getHeight());
                    result.setLogicalHeight(decodeResult.getWidth());
                }
            }
            result.setOrientation(orientation);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fd != null) {
                try {
                    fd.close();
                } catch (IOException ignored) {
                }
            }
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ignored) {
                }
            }

            // Put result in cache, regardless of null.  The cache will handle null results.
            mCache.put(mKey, result);
            if (result != null) {
                result.acquireReference();
                if (DEBUG) {
                    Log.d(TAG, "placed result in cache: key=" + mKey + " bmp="
                        + result + " cancelled=" + isCancelled());
                }
            } else if (mInBitmap != null) {
                if (DEBUG) {
                    Log.d(TAG, "placing failed/cancelled bitmap in pool: key="
                        + mKey + " bmp=" + mInBitmap);
                }
                mCache.offer(mInBitmap);
            }
        }
        return result;
    }

    /**
     * Return an input stream that can be read from the beginning using the most efficient way,
     * given an input stream that may or may not support reset(), or given null.
     *
     * The returned input stream may or may not be the same stream.
     */
    private InputStream reset(InputStream in) throws IOException {
        Trace.beginSection("create stream");
        if (in == null) {
            in = mKey.createInputStream();
        } else if (in.markSupported()) {
            in.reset();
        } else {
            try {
                in.close();
            } catch (IOException ignored) {
            }
            in = mKey.createInputStream();
        }
        Trace.endSection();
        return in;
    }

    private Bitmap decode(ParcelFileDescriptor fd, InputStream in) {
        final Bitmap result;
        if (fd != null) {
            result = BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor(), null, mOpts);
        } else {
            result = BitmapFactory.decodeStream(in, null, mOpts);
        }
        return result;
    }

    public void cancel() {
        cancel(true);
        mOpts.requestCancelDecode();
    }

    @Override
    protected void onProgressUpdate(Void... values) {
        mDecodeCallback.onDecodeBegin(mKey);
    }

    @Override
    public void onPostExecute(ReusableBitmap result) {
        mDecodeCallback.onDecodeComplete(mKey, result);
    }

    @Override
    protected void onCancelled(ReusableBitmap result) {
        mDecodeCallback.onDecodeCancel(mKey);
        if (result == null) {
            return;
        }

        result.releaseReference();
        if (mInBitmap == null) {
            // not reusing bitmaps: can recycle immediately
            result.bmp.recycle();
        }
    }

    /**
     * Parameters to pass to the DecodeTask.
     */
    public static class DecodeOptions {

        /**
         * Round sample size to the nearest power of 2. Depending on the source and destination
         * dimensions, we will either truncate, in which case we decode from a bigger region and
         * crop down, or we will round up, in which case we decode from a smaller region and scale
         * up.
         */
        public static final int STRATEGY_ROUND_NEAREST = 0;
        /**
         * Always decode from a bigger region and crop down.
         */
        public static final int STRATEGY_TRUNCATE = 1;

        /**
         * Always decode from a smaller region and scale up.
         */
        public static final int STRATEGY_ROUND_UP = 2;

        /**
         * The destination width to decode to.
         */
        public int destW;
        /**
         * The destination height to decode to.
         */
        public int destH;
        /**
         * If the destination dimensions are smaller than the source image provided by the request
         * key, this will determine where vertically the destination rect will be cropped from.
         * Value from 0f for top-most crop to 1f for bottom-most crop.
         */
        public float verticalCenter;
        /**
         * One of the STRATEGY constants.
         */
        public int sampleSizeStrategy;

        public DecodeOptions(final int destW, final int destH) {
            this(destW, destH, 0.5f, STRATEGY_ROUND_NEAREST);
        }

        /**
         * Create new DecodeOptions.
         * @param destW The destination width to decode to.
         * @param destH The destination height to decode to.
         * @param verticalCenter If the destination dimensions are smaller than the source image
         *                       provided by the request key, this will determine where vertically
         *                       the destination rect will be cropped from.
         * @param sampleSizeStrategy One of the STRATEGY constants.
         */
        public DecodeOptions(final int destW, final int destH, final float verticalCenter,
                final int sampleSizeStrategy) {
            this.destW = destW;
            this.destH = destH;
            this.verticalCenter = verticalCenter;
            this.sampleSizeStrategy = sampleSizeStrategy;
        }
    }
}
