/*
 * Copyright (C) 2017 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.wallpaper.asset;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.media.ExifInterface;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import androidx.annotation.Nullable;

import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Represents Asset types for which bytes can be read directly, allowing for flexible bitmap
 * decoding.
 */
public abstract class StreamableAsset extends Asset {
    private static final ExecutorService sExecutorService = Executors.newCachedThreadPool();
    private static final String TAG = "StreamableAsset";

    private BitmapRegionDecoder mBitmapRegionDecoder;
    private Point mDimensions;

    /**
     * Scales and returns a new Rect from the given Rect by the given scaling factor.
     */
    public static Rect scaleRect(Rect rect, float scale) {
        return new Rect(
                Math.round((float) rect.left * scale),
                Math.round((float) rect.top * scale),
                Math.round((float) rect.right * scale),
                Math.round((float) rect.bottom * scale));
    }

    /**
     * Maps from EXIF orientation tag values to counterclockwise degree rotation values.
     */
    private static int getDegreesRotationForExifOrientation(int exifOrientation) {
        switch (exifOrientation) {
            case ExifInterface.ORIENTATION_NORMAL:
                return 0;
            case ExifInterface.ORIENTATION_ROTATE_90:
                return 90;
            case ExifInterface.ORIENTATION_ROTATE_180:
                return 180;
            case ExifInterface.ORIENTATION_ROTATE_270:
                return 270;
            default:
                Log.w(TAG, "Unsupported EXIF orientation " + exifOrientation);
                return 0;
        }
    }

    @Override
    public void decodeBitmap(int targetWidth, int targetHeight,
                             BitmapReceiver receiver) {
        sExecutorService.execute(() -> {
            int newTargetWidth = targetWidth;
            int newTargetHeight = targetHeight;
            int exifOrientation = getExifOrientation();
            // Switch target height and width if image is rotated 90 or 270 degrees.
            if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90
                    || exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
                int tempHeight = newTargetHeight;
                newTargetHeight = newTargetWidth;
                newTargetWidth = tempHeight;
            }

            BitmapFactory.Options options = new BitmapFactory.Options();

            Point rawDimensions = calculateRawDimensions();
            // Raw dimensions may be null if there was an error opening the underlying input stream.
            if (rawDimensions == null) {
                decodeBitmapCompleted(receiver, null);
                return;
            }
            options.inSampleSize = BitmapUtils.calculateInSampleSize(
                    rawDimensions.x, rawDimensions.y, newTargetWidth, newTargetHeight);
            options.inPreferredConfig = Config.HARDWARE;

            InputStream inputStream = openInputStream();
            Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);
            closeInputStream(
                    inputStream, "Error closing the input stream used to decode the full bitmap");

            // Rotate output bitmap if necessary because of EXIF orientation tag.
            int matrixRotation = getDegreesRotationForExifOrientation(exifOrientation);
            if (matrixRotation > 0) {
                Matrix rotateMatrix = new Matrix();
                rotateMatrix.setRotate(matrixRotation);
                bitmap = Bitmap.createBitmap(
                        bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), rotateMatrix, false);
            }
            decodeBitmapCompleted(receiver, bitmap);
        });
    }

    @Override
    public void decodeRawDimensions(Activity unused, DimensionsReceiver receiver) {
        sExecutorService.execute(() -> {
            Point result = calculateRawDimensions();
            new Handler(Looper.getMainLooper()).post(() -> {
                receiver.onDimensionsDecoded(result);
            });
        });
    }

    @Override
    public void decodeBitmapRegion(Rect rect, int targetWidth, int targetHeight,
            boolean shouldAdjustForRtl, BitmapReceiver receiver) {
        runDecodeBitmapRegionTask(rect, targetWidth, targetHeight, shouldAdjustForRtl, receiver);
    }

    @Override
    public boolean supportsTiling() {
        return true;
    }

    /**
     * Fetches an input stream of bytes for the wallpaper image asset and provides the stream
     * asynchronously back to a {@link StreamReceiver}.
     */
    public void fetchInputStream(final StreamReceiver streamReceiver) {
        sExecutorService.execute(() -> {
            InputStream result = openInputStream();
            new Handler(Looper.getMainLooper()).post(() -> {
                streamReceiver.onInputStreamOpened(result);
            });
        });
    }

    /**
     * Returns an InputStream representing the asset. Should only be called off the main UI thread.
     */
    @Nullable
    protected abstract InputStream openInputStream();

    /**
     * Gets the EXIF orientation value of the asset. This method should only be called off the main UI
     * thread.
     */
    protected int getExifOrientation() {
        // By default, assume that the EXIF orientation is normal (i.e., bitmap is rotated 0 degrees
        // from how it should be rendered to a viewer).
        return ExifInterface.ORIENTATION_NORMAL;
    }

    /**
     * Decodes and downscales a bitmap region off the main UI thread.
     *
     * @param rect         Rect representing the crop region in terms of the original image's resolution.
     * @param targetWidth  Width of target view in physical pixels.
     * @param targetHeight Height of target view in physical pixels.
     * @param isRtl
     * @param receiver     Called with the decoded bitmap region or null if there was an error decoding
     *                     the bitmap region.
     */
    public void runDecodeBitmapRegionTask(Rect rect, int targetWidth, int targetHeight,
            boolean isRtl, BitmapReceiver receiver) {
        sExecutorService.execute(() -> {
            int newTargetWidth = targetWidth;
            int newTargetHeight = targetHeight;
            Rect cropRect = rect;
            int exifOrientation = getExifOrientation();
            // Switch target height and width if image is rotated 90 or 270 degrees.
            if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90
                    || exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
                int tempHeight = newTargetHeight;
                newTargetHeight = newTargetWidth;
                newTargetWidth = tempHeight;
            }

            // Rotate crop rect if image is rotated more than 0 degrees.
            Point dimensions = calculateRawDimensions();
            cropRect = CropRectRotator.rotateCropRectForExifOrientation(
                    dimensions, cropRect, exifOrientation);

            // If we're in RTL mode, center in the rightmost side of the image
            if (isRtl) {
                cropRect.set(dimensions.x - cropRect.right, cropRect.top,
                        dimensions.x - cropRect.left, cropRect.bottom);
            }

            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inSampleSize = BitmapUtils.calculateInSampleSize(
                    cropRect.width(), cropRect.height(), newTargetWidth, newTargetHeight);

            if (mBitmapRegionDecoder == null) {
                mBitmapRegionDecoder = openBitmapRegionDecoder();
            }

            // Bitmap region decoder may have failed to open if there was a problem with the
            // underlying InputStream.
            if (mBitmapRegionDecoder != null) {
                try {
                    Bitmap bitmap = mBitmapRegionDecoder.decodeRegion(cropRect, options);

                    // Rotate output bitmap if necessary because of EXIF orientation.
                    int matrixRotation = getDegreesRotationForExifOrientation(exifOrientation);
                    if (matrixRotation > 0) {
                        Matrix rotateMatrix = new Matrix();
                        rotateMatrix.setRotate(matrixRotation);
                        bitmap = Bitmap.createBitmap(
                                bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), rotateMatrix,
                                false);
                    }
                    decodeBitmapCompleted(receiver, bitmap);
                    return;
                } catch (OutOfMemoryError e) {
                    Log.e(TAG, "Out of memory and unable to decode bitmap region", e);
                } catch (IllegalArgumentException e) {
                    Log.e(TAG, "Illegal argument for decoding bitmap region", e);
                }
            }
            decodeBitmapCompleted(receiver, null);
        });
    }

    /**
     * Decodes the raw dimensions of the asset without allocating memory for the entire asset. Adjusts
     * for the EXIF orientation if necessary.
     *
     * @return Dimensions as a Point where width is represented by "x" and height by "y".
     */
    @Nullable
    public Point calculateRawDimensions() {
        if (mDimensions != null) {
            return mDimensions;
        }

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        InputStream inputStream = openInputStream();
        // Input stream may be null if there was an error opening it.
        if (inputStream == null) {
            return null;
        }
        BitmapFactory.decodeStream(inputStream, null, options);
        closeInputStream(inputStream, "There was an error closing the input stream used to calculate "
                + "the image's raw dimensions");

        int exifOrientation = getExifOrientation();
        // Swap height and width if image is rotated 90 or 270 degrees.
        if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90
                || exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
            mDimensions = new Point(options.outHeight, options.outWidth);
        } else {
            mDimensions = new Point(options.outWidth, options.outHeight);
        }

        return mDimensions;
    }

    /**
     * Returns a BitmapRegionDecoder for the asset.
     */
    @Nullable
    private BitmapRegionDecoder openBitmapRegionDecoder() {
        InputStream inputStream = null;
        BitmapRegionDecoder brd = null;

        try {
            inputStream = openInputStream();
            // Input stream may be null if there was an error opening it.
            if (inputStream == null) {
                return null;
            }
            brd = BitmapRegionDecoder.newInstance(inputStream, true);
        } catch (IOException e) {
            Log.w(TAG, "Unable to open BitmapRegionDecoder", e);
        } finally {
            closeInputStream(inputStream, "Unable to close input stream used to create "
                    + "BitmapRegionDecoder");
        }

        return brd;
    }

    /**
     * Closes the provided InputStream and if there was an error, logs the provided error message.
     */
    private void closeInputStream(InputStream inputStream, String errorMessage) {
        try {
            if (inputStream != null) {
                inputStream.close();
            }
        } catch (IOException e) {
            Log.e(TAG, errorMessage);
        }
    }

    /**
     * Interface for receiving unmodified input streams of the underlying asset without any
     * downscaling or other decoding options.
     */
    public interface StreamReceiver {

        /**
         * Called with an opened input stream of bytes from the underlying image asset. Clients must
         * close the input stream after it has been read. Returns null if there was an error opening the
         * input stream.
         */
        void onInputStreamOpened(@Nullable InputStream inputStream);
    }
}



