/*
 * 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 = mCameraManager.getCameraCharacteristics(cameraId);
        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.getId(), mCameraManager);
        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);
        }
    }
}
