/*
 * Copyright 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 android.hardware.camera2.cts;

import static android.hardware.camera2.cts.CameraTestUtils.*;

import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.Size;
import android.media.Image;
import android.media.ImageReader;
import android.os.Environment;
import android.os.Handler;
import android.test.AndroidTestCase;
import android.util.Log;
import android.view.Surface;

import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>Basic test for ImageReader APIs. It uses CameraDevice as producer, camera
 * sends the data to the surface provided by imageReader. Below image formats
 * are tested:</p>
 *
 * <p>YUV_420_888: flexible YUV420, it is mandatory format for camera. </p>
 * <p>JPEG: used for JPEG still capture, also mandatory format. </p>
 * <p>Some invalid access test. </p>
 * <p>TODO: Add more format tests? </p>
 */
public class ImageReaderTest extends AndroidTestCase {
    private static final String TAG = "ImageReaderTest";
    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
    private static final boolean DUMP_FILE = false;
    private static final String DEBUG_FILE_NAME_BASE =
            Environment.getExternalStorageDirectory().getPath();
    // number of frame (for streaming requests) to be verified.
    // TODO: Need extend it to bigger number
    private static final int NUM_FRAME_VERIFIED = 1;
    // Max number of images can be accessed simultaneously from ImageReader.
    private static final int MAX_NUM_IMAGES = 5;

    private CameraManager mCameraManager;
    private CameraDevice mCamera;
    private String[] mCameraIds;
    private ImageReader mReader = null;
    private Handler mHandler = null;
    private SimpleImageListener mListener = null;
    private CameraTestThread mLooperThread = null;

    @Override
    public void setContext(Context context) {
        super.setContext(context);
        mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
        assertNotNull("Can't connect to camera manager!", mCameraManager);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mCameraIds = mCameraManager.getCameraIdList();
        mLooperThread = new CameraTestThread();
        mHandler = mLooperThread.start();
    }

    @Override
    protected void tearDown() throws Exception {
        if (mCamera != null) {
            mCamera.close();
            mCamera = null;
        }
        if (mReader != null) {
            mReader.close();
            mReader = null;
        }
        mLooperThread.close();
        mHandler = null;
        super.tearDown();
    }

    public void testImageReaderFromCameraFlexibleYuv() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            Log.i(TAG, "Testing Camera " + mCameraIds[i]);
            openDevice(mCameraIds[i]);
            bufferFormatTestByCamera(ImageFormat.YUV_420_888, mCameraIds[i]);
            closeDevice(mCameraIds[i]);
        }
    }

    public void testImageReaderFromCameraJpeg() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            Log.v(TAG, "Testing Camera " + mCameraIds[i]);
            openDevice(mCameraIds[i]);
            bufferFormatTestByCamera(ImageFormat.JPEG, mCameraIds[i]);
            closeDevice(mCameraIds[i]);
        }
    }

    public void testImageReaderFromCameraRaw() {
        // TODO: can test this once raw is supported
    }

    public void testImageReaderInvalidAccessTest() {
        // TODO: test invalid access case, see if we can receive expected
        // exceptions
    }

    private void bufferFormatTestByCamera(int format, String cameraId) throws Exception {
        CameraCharacteristics properties = mCamera.getProperties();
        assertNotNull("Can't get camera properties!", properties);

        /**
         * TODO: cleanup the color format mess, we probably need define formats
         * in Image class instead of using ImageFormat for camera. also,
         * probably make sense to change the available format type from Enum[]
         * to int[]. It'll also be nice to put this into a helper function and
         * move to util class.
         */
        // Comment out below check to work around b/10406212.
        /*
        int[] availableFormats = properties.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS);
        assertArrayNotEmpty(availableFormats,
                "availableFormats should not be empty");
        Arrays.sort(availableFormats);
        assertTrue("Can't find the format " + format + " in supported formats " +
                Arrays.toString(availableFormats),
                Arrays.binarySearch(availableFormats, format) >= 0);
        */

        Size[] availableSizes = getSupportedSizeForFormat(format, mCamera);
        assertArrayNotEmpty(availableSizes, "availableSizes should not be empty");

        // for each resolution, test imageReader:
        for (Size sz : availableSizes) {
            if (VERBOSE) Log.v(TAG, "Testing size " + sz.toString() + " for camera " + cameraId);

            prepareImageReader(sz, format);

            CaptureRequest request = prepareCaptureRequest(format);

            captureAndValidateImage(request, sz, format);

            stopCapture();
        }
    }

    private class SimpleImageListener implements ImageReader.OnImageAvailableListener {
        private int mPendingImages = 0;
        private final Object mImageSyncObject = new Object();

        @Override
        public void onImageAvailable(ImageReader reader) {
            if (VERBOSE) Log.v(TAG, "new image available");
            synchronized (mImageSyncObject) {
                mPendingImages++;
                mImageSyncObject.notifyAll();
            }
        }

        public boolean isImagePending() {
            synchronized (mImageSyncObject) {
                return (mPendingImages > 0);
            }
        }

        public void waitForImage() {
            final int TIMEOUT_MS = 5000;
            synchronized (mImageSyncObject) {
                while (mPendingImages == 0) {
                    try {
                        if (VERBOSE)
                            Log.d(TAG, "waiting for next image");
                        mImageSyncObject.wait(TIMEOUT_MS);
                        if (mPendingImages == 0) {
                            fail("wait for next image timed out");
                        }
                    } catch (InterruptedException ie) {
                        throw new RuntimeException(ie);
                    }
                }
                mPendingImages--;
            }
        }
    }

    private void prepareImageReader(Size sz, int format) throws Exception {
        int width = sz.getWidth();
        int height = sz.getHeight();
        mReader = ImageReader.newInstance(width, height, format, MAX_NUM_IMAGES);
        mListener  = new SimpleImageListener();
        mReader.setOnImageAvailableListener(mListener, mHandler);
        if (VERBOSE) Log.v(TAG, "Preparing ImageReader size " + sz.toString());
    }

    private CaptureRequest prepareCaptureRequest(int format) throws Exception {
        List<Surface> outputSurfaces = new ArrayList<Surface>(1);
        Surface surface = mReader.getSurface();
        assertNotNull("Fail to get surface from ImageReader", surface);
        outputSurfaces.add(surface);
        mCamera.configureOutputs(outputSurfaces);

        CaptureRequest.Builder captureBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        assertNotNull("Fail to get captureRequest", captureBuilder);
        captureBuilder.addTarget(mReader.getSurface());

        return captureBuilder.build();
    }

    private void captureAndValidateImage(CaptureRequest request,
            Size sz, int format) throws Exception {
        // TODO: Add more format here, and wrap each one as a function.
        Image img;
        int captureCount = NUM_FRAME_VERIFIED;
        // Only verify single image for still capture
        if (format == ImageFormat.JPEG) {
            captureCount = 1;
            mCamera.capture(request, null, null);
        } else {
            mCamera.setRepeatingRequest(request, null, null);
        }

        for (int i = 0; i < captureCount; i++) {
            assertNotNull("Image listener is null", mListener);
            if (VERBOSE) Log.v(TAG, "Waiting for an Image");
            mListener.waitForImage();
            img = mReader.acquireNextImage();
            if (VERBOSE) Log.v(TAG, "Got next image");
            validateImage(img, sz.getWidth(), sz.getHeight(), format);
            img.close();
            // Return the pending images to producer in case the validation is slower
            // than the image producing rate. Otherwise, it could cause the producer
            // starvation.
            while (mListener.isImagePending()) {
                mListener.waitForImage();
                img = mReader.acquireNextImage();
                img.close();
            }
        }
    }

    private void stopCapture() throws CameraAccessException {
        mCamera.stopRepeating();
        mCamera.waitUntilIdle();
        mReader.close();
        mReader = null;
        mListener = null;
    }

    private void openDevice(String cameraId) {
        if (mCamera != null) {
            throw new IllegalStateException("Already have open camera device");
        }
        try {
            mCamera = openCamera(mCameraManager, cameraId, mHandler);
        } catch (CameraAccessException e) {
            mCamera = null;
            fail("Fail to open camera, " + Log.getStackTraceString(e));
        } catch (BlockingOpenException e) {
            mCamera = null;
            fail("Fail to open camera, " + Log.getStackTraceString(e));
        }
    }

    private void closeDevice(String cameraId) {
        mCamera.close();
        mCamera = null;
    }

    private void validateImage(Image image, int width, int height, int format) {
        checkImage(image, width, height, format);

        /**
         * TODO: validate timestamp:
         * 1. capture result timestamp against the image timestamp (need
         * consider frame drops)
         * 2. timestamps should be monotonically increasing for different requests
         */
        if(VERBOSE) Log.v(TAG, "validating Image");
        byte[] data = getDataFromImage(image);
        assertTrue("Invalid image data", data != null && data.length > 0);

        if (format == ImageFormat.JPEG) {
            validateJpegData(data, width, height);
        } else {
            validateYuvData(data, width, height, format, image.getTimestamp());
        }
    }

    private void validateJpegData(byte[] jpegData, int width, int height) {
        BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
        // DecodeBound mode: only parse the frame header to get width/height.
        // it doesn't decode the pixel.
        bmpOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, bmpOptions);
        assertEquals(width, bmpOptions.outWidth);
        assertEquals(height, bmpOptions.outHeight);

        // Pixel decoding mode: decode whole image. check if the image data
        // is decodable here.
        assertNotNull("Decoding jpeg failed",
                BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length));
        if (DUMP_FILE) {
            String fileName =
                    DEBUG_FILE_NAME_BASE + width + "x" + height + ".yuv";
            dumpFile(fileName, jpegData);
        }
    }

    private void validateYuvData(byte[] yuvData, int width, int height, int format, long ts) {
        checkYuvFormat(format);
        if (VERBOSE) Log.v(TAG, "Validating YUV data");
        int expectedSize = width * height * ImageFormat.getBitsPerPixel(format) / 8;
        assertEquals("Yuv data doesn't match", expectedSize, yuvData.length);

        // TODO: Can add data validation if we have test pattern(tracked by b/9625427)

        if (DUMP_FILE) {
            String fileName =
                    DEBUG_FILE_NAME_BASE + "/" + width + "x" + height + "_" + ts / 1e6 + ".yuv";
            dumpFile(fileName, yuvData);
        }
    }
}
