/*
 * Copyright (C) 2014 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.camera.data;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Point;
import android.media.MediaMetadataRetriever;

import com.android.camera.debug.Log;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import javax.microedition.khronos.opengles.GL11;

/**
 * An utility class for data in content provider.
 */
public class LocalDataUtil {

    private static final Log.Tag TAG = new Log.Tag("LocalDataUtil");

    /**
     * @param mimeType The MIME type to check.
     * @return Whether the MIME is a video type.
     */
    public static boolean isMimeTypeVideo(String mimeType) {
        return mimeType.startsWith("video/");
    }

    /**
     * @param mimeType The MIME type to check.
     * @return Whether the MIME is a image type.
     */
    public static boolean isMimeTypeImage(String mimeType) {
        return mimeType.startsWith("image/");
    }

    /**
     * Decodes the dimension of a bitmap.
     *
     * @param path The path to the bitmap.
     * @return The decoded width/height is stored in Point.x/Point.y
     *         respectively.
     */
    public static Point decodeBitmapDimension(String path) {
        Point size = null;
        InputStream is = null;
        try {
            is = new FileInputStream(path);
            size = decodeBitmapDimension(is);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) { }
            }
        }
        return size;
    }

    /**
     * Decodes the dimension of a bitmap.
     *
     * @param is An input stream with the data of the bitmap.
     * @return The decoded width/height is stored in Point.x/Point.y
     *         respectively.
     */
    public static Point decodeBitmapDimension(InputStream is) {
        Point size = null;
        BitmapFactory.Options justBoundsOpts = new BitmapFactory.Options();
        justBoundsOpts.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(is, null, justBoundsOpts);
        if (justBoundsOpts.outWidth > 0 && justBoundsOpts.outHeight > 0) {
            size = new Point(justBoundsOpts.outWidth, justBoundsOpts.outHeight);
        } else {
            Log.e(TAG, "Bitmap dimension decoding failed");
        }
        return size;
    }

    /**
     * Load the thumbnail of an image from an {@link java.io.InputStream}.
     *
     * @param stream The input stream of the image.
     * @param imageWidth Image width.
     * @param imageHeight Image height.
     * @param widthBound The bound of the width of the decoded image.
     * @param heightBound The bound of the height of the decoded image.
     * @param orientation The orientation of the image. The image will be rotated
     *                    clockwise in degrees.
     * @param maximumPixels The bound for the number of pixels of the decoded image.
     * @return {@code null} if the decoding failed.
     */
    public static Bitmap loadImageThumbnailFromStream(InputStream stream, int imageWidth,
            int imageHeight, int widthBound, int heightBound, int orientation,
            int maximumPixels) {

        /** 32K buffer. */
        byte[] decodeBuffer = new byte[32 * 1024];

        if (orientation % 180 != 0) {
            int dummy = imageHeight;
            imageHeight = imageWidth;
            imageWidth = dummy;
        }

        // Generate Bitmap of maximum size that fits into widthBound x heightBound.
        // Algorithm: start with full size and step down in powers of 2.
        int targetWidth = imageWidth;
        int targetHeight = imageHeight;
        int sampleSize = 1;
        while (targetHeight > heightBound || targetWidth > widthBound ||
                targetHeight > GL11.GL_MAX_TEXTURE_SIZE || targetWidth > GL11.GL_MAX_TEXTURE_SIZE ||
                targetHeight * targetWidth > maximumPixels) {
            sampleSize <<= 1;
            targetWidth = imageWidth / sampleSize;
            targetHeight = imageWidth / sampleSize;
        }

        // For large (> MAXIMUM_TEXTURE_SIZE) high aspect ratio (panorama)
        // Bitmap requests:
        //   Step 1: ask for double size.
        //   Step 2: scale maximum edge down to MAXIMUM_TEXTURE_SIZE.
        //
        // Here's the step 1: double size.
        if ((heightBound > GL11.GL_MAX_TEXTURE_SIZE || widthBound > GL11.GL_MAX_TEXTURE_SIZE) &&
                targetWidth * targetHeight < maximumPixels / 4 && sampleSize > 1) {
            sampleSize >>= 2;
        }

        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inSampleSize = sampleSize;
        opts.inTempStorage = decodeBuffer;
        Bitmap b = BitmapFactory.decodeStream(stream, null, opts);

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

        // Step 2: scale maximum edge down to maximum texture size.
        // If Bitmap maximum edge > MAXIMUM_TEXTURE_SIZE, which can happen for panoramas,
        // scale to fit in MAXIMUM_TEXTURE_SIZE.
        if (b.getWidth() > GL11.GL_MAX_TEXTURE_SIZE || b.getHeight() >
                GL11.GL_MAX_TEXTURE_SIZE) {
            int maxEdge = Math.max(b.getWidth(), b.getHeight());
            b = Bitmap.createScaledBitmap(b, b.getWidth() * GL11.GL_MAX_TEXTURE_SIZE / maxEdge,
                    b.getHeight() * GL11.GL_MAX_TEXTURE_SIZE / maxEdge, false);
        }

        // Not called often because most modes save image data non-rotated.
        if (orientation != 0 && b != null) {
            Matrix m = new Matrix();
            m.setRotate(orientation);
            b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), m, false);
        }

        return b;
    }

    /**
     * Loads the thumbnail of a video.
     *
     * @param path The path to the video file.
     * @return {@code null} if the loading failed.
     */
    public static Bitmap loadVideoThumbnail(String path) {
        Bitmap bitmap = null;
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        try {
            retriever.setDataSource(path);
            byte[] data = retriever.getEmbeddedPicture();
            if (data != null) {
                bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
            }
            if (bitmap == null) {
                bitmap = retriever.getFrameAtTime();
            }
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "MediaMetadataRetriever.setDataSource() fail:" + e.getMessage());
        }
        retriever.release();
        return bitmap;
    }
}
