/*
 * 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.mediaframeworktest.integration;

import static android.hardware.camera2.CameraDevice.TEMPLATE_PREVIEW;

import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;

import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.ICameraService;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.ICameraDeviceUser;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.CaptureResultExtras;
import android.hardware.camera2.impl.PhysicalCaptureResultInfo;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.utils.SubmitInfo;
import android.media.Image;
import android.media.ImageReader;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import android.view.Surface;

import com.android.mediaframeworktest.MediaFrameworkIntegrationTestRunner;

import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;

public class CameraDeviceBinderTest extends AndroidTestCase {
    private static String TAG = "CameraDeviceBinderTest";
    // Number of streaming callbacks need to check.
    private static int NUM_CALLBACKS_CHECKED = 10;
    // Wait for capture result timeout value: 1500ms
    private final static int WAIT_FOR_COMPLETE_TIMEOUT_MS = 1500;
    // Wait for flush timeout value: 1000ms
    private final static int WAIT_FOR_FLUSH_TIMEOUT_MS = 1000;
    // Wait for idle timeout value: 2000ms
    private final static int WAIT_FOR_IDLE_TIMEOUT_MS = 2000;
    // Wait while camera device starts working on requests
    private final static int WAIT_FOR_WORK_MS = 300;
    // Default size is VGA, which is mandatory camera supported image size by CDD.
    private static final int DEFAULT_IMAGE_WIDTH = 640;
    private static final int DEFAULT_IMAGE_HEIGHT = 480;
    private static final int MAX_NUM_IMAGES = 5;

    private String mCameraId;
    private ICameraDeviceUser mCameraUser;
    private CameraBinderTestUtils mUtils;
    private ICameraDeviceCallbacks.Stub mMockCb;
    private Surface mSurface;
    private OutputConfiguration mOutputConfiguration;
    private HandlerThread mHandlerThread;
    private Handler mHandler;
    ImageReader mImageReader;

    public CameraDeviceBinderTest() {
    }

    private class ImageDropperListener implements ImageReader.OnImageAvailableListener {

        @Override
        public void onImageAvailable(ImageReader reader) {
            Image image = reader.acquireNextImage();
            if (image != null) image.close();
        }
    }

    public class DummyCameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {

        /*
         * (non-Javadoc)
         * @see
         * android.hardware.camera2.ICameraDeviceCallbacks#onDeviceError(int,
         * android.hardware.camera2.CaptureResultExtras)
         */
        public void onDeviceError(int errorCode, CaptureResultExtras resultExtras)
                throws RemoteException {
            // TODO Auto-generated method stub

        }

        /*
         * (non-Javadoc)
         * @see android.hardware.camera2.ICameraDeviceCallbacks#onDeviceIdle()
         */
        public void onDeviceIdle() throws RemoteException {
            // TODO Auto-generated method stub

        }

        /*
         * (non-Javadoc)
         * @see
         * android.hardware.camera2.ICameraDeviceCallbacks#onCaptureStarted(
         * android.hardware.camera2.CaptureResultExtras, long)
         */
        public void onCaptureStarted(CaptureResultExtras resultExtras, long timestamp)
                throws RemoteException {
            // TODO Auto-generated method stub

        }

        /*
         * (non-Javadoc)
         * @see
         * android.hardware.camera2.ICameraDeviceCallbacks#onResultReceived(
         * android.hardware.camera2.impl.CameraMetadataNative,
         * android.hardware.camera2.CaptureResultExtras)
         */
        public void onResultReceived(CameraMetadataNative result, CaptureResultExtras resultExtras,
                PhysicalCaptureResultInfo physicalResults[]) throws RemoteException {
            // TODO Auto-generated method stub

        }

        /*
         * (non-Javadoc)
         * @see android.hardware.camera2.ICameraDeviceCallbacks#onPrepared()
         */
        @Override
        public void onPrepared(int streamId) throws RemoteException {
            // TODO Auto-generated method stub

        }

        /*
         * (non-Javadoc)
         * @see android.hardware.camera2.ICameraDeviceCallbacks#onRequestQueueEmpty()
         */
        @Override
        public void onRequestQueueEmpty() throws RemoteException {
            // TODO Auto-generated method stub

        }

        /*
         * (non-Javadoc)
         * @see android.hardware.camera2.ICameraDeviceCallbacks#onRepeatingRequestError()
         */
        @Override
        public void onRepeatingRequestError(long lastFrameNumber, int repeatingRequestId) {
            // TODO Auto-generated method stub
        }
    }

    class IsMetadataNotEmpty implements ArgumentMatcher<CameraMetadataNative> {
        @Override
        public boolean matches(CameraMetadataNative obj) {
            return !obj.isEmpty();
        }
    }

    private void createDefaultSurface() {
        mImageReader =
                ImageReader.newInstance(DEFAULT_IMAGE_WIDTH,
                        DEFAULT_IMAGE_HEIGHT,
                        ImageFormat.YUV_420_888,
                        MAX_NUM_IMAGES);
        mImageReader.setOnImageAvailableListener(new ImageDropperListener(), mHandler);
        mSurface = mImageReader.getSurface();
        mOutputConfiguration = new OutputConfiguration(mSurface);
    }

    private CaptureRequest.Builder createDefaultBuilder(boolean needStream) throws Exception {
        CameraMetadataNative metadata = null;
        assertTrue(metadata.isEmpty());

        metadata = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW);
        assertFalse(metadata.isEmpty());

        CaptureRequest.Builder request = new CaptureRequest.Builder(metadata, /*reprocess*/false,
                CameraCaptureSession.SESSION_ID_NONE, mCameraId, /*physicalCameraIdSet*/null);
        assertFalse(request.isEmpty());
        assertFalse(metadata.isEmpty());
        if (needStream) {
            int streamId = mCameraUser.createStream(mOutputConfiguration);
            assertEquals(0, streamId);
            request.addTarget(mSurface);
        }
        return request;
    }

    private SubmitInfo submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception {
        SubmitInfo requestInfo = mCameraUser.submitRequest(request, streaming);
        assertTrue(
                "Request IDs should be non-negative (expected: >= 0, actual: " +
                requestInfo.getRequestId() + ")",
                requestInfo.getRequestId() >= 0);
        return requestInfo;
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        /**
         * Workaround for mockito and JB-MR2 incompatibility
         *
         * Avoid java.lang.IllegalArgumentException: dexcache == null
         * https://code.google.com/p/dexmaker/issues/detail?id=2
         */
        System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
        mUtils = new CameraBinderTestUtils(getContext());

        // This cannot be set in the constructor, since the onCreate isn't
        // called yet
        mCameraId = MediaFrameworkIntegrationTestRunner.mCameraId;

        ICameraDeviceCallbacks.Stub dummyCallbacks = new DummyCameraDeviceCallbacks();

        String clientPackageName = getContext().getPackageName();

        mMockCb = spy(dummyCallbacks);

        mCameraUser = mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
                clientPackageName, ICameraService.USE_CALLING_UID);
        assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser);
        mHandlerThread = new HandlerThread(TAG);
        mHandlerThread.start();
        mHandler = new Handler(mHandlerThread.getLooper());
        createDefaultSurface();

        Log.v(TAG, String.format("Camera %s connected", mCameraId));
    }

    @Override
    protected void tearDown() throws Exception {
        mCameraUser.disconnect();
        mCameraUser = null;
        mSurface.release();
        mImageReader.close();
        mHandlerThread.quitSafely();
    }

    @SmallTest
    public void testCreateDefaultRequest() throws Exception {
        CameraMetadataNative metadata = null;
        assertTrue(metadata.isEmpty());

        metadata = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW);
        assertFalse(metadata.isEmpty());

    }

    @SmallTest
    public void testCreateStream() throws Exception {
        int streamId = mCameraUser.createStream(mOutputConfiguration);
        assertEquals(0, streamId);

        try {
            mCameraUser.createStream(mOutputConfiguration);
            fail("Creating same stream twice");
        } catch (ServiceSpecificException e) {
            assertEquals("Creating same stream twice",
                    e.errorCode, ICameraService.ERROR_ALREADY_EXISTS);
        }

        mCameraUser.deleteStream(streamId);
    }

    @SmallTest
    public void testDeleteInvalidStream() throws Exception {
        int[] badStreams = { -1, 0, 1, 0xC0FFEE };
        for (int badStream : badStreams) {
            try {
                mCameraUser.deleteStream(badStream);
                fail("Allowed bad stream delete");
            } catch (ServiceSpecificException e) {
                assertEquals(e.errorCode, ICameraService.ERROR_ILLEGAL_ARGUMENT);
            }
        }
    }

    @SmallTest
    public void testCreateStreamTwo() throws Exception {

        // Create first stream
        int streamId = mCameraUser.createStream(mOutputConfiguration);
        assertEquals(0, streamId);

        try {
            mCameraUser.createStream(mOutputConfiguration);
            fail("Created same stream twice");
        } catch (ServiceSpecificException e) {
            assertEquals("Created same stream twice",
                    ICameraService.ERROR_ALREADY_EXISTS, e.errorCode);
        }

        // Create second stream with a different surface.
        SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
        surfaceTexture.setDefaultBufferSize(640, 480);
        Surface surface2 = new Surface(surfaceTexture);
        OutputConfiguration output2 = new OutputConfiguration(surface2);

        int streamId2 = mCameraUser.createStream(output2);
        assertEquals(1, streamId2);

        // Clean up streams
        mCameraUser.deleteStream(streamId);
        mCameraUser.deleteStream(streamId2);
    }

    @SmallTest
    public void testSubmitBadRequest() throws Exception {

        CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */false);
        CaptureRequest request1 = builder.build();
        try {
            SubmitInfo requestInfo = mCameraUser.submitRequest(request1, /* streaming */false);
            fail("Exception expected");
        } catch(ServiceSpecificException e) {
            assertEquals("Expected submitRequest to throw ServiceSpecificException with BAD_VALUE " +
                    "since we had 0 surface targets set.", ICameraService.ERROR_ILLEGAL_ARGUMENT,
                    e.errorCode);
        }

        builder.addTarget(mSurface);
        CaptureRequest request2 = builder.build();
        try {
            SubmitInfo requestInfo = mCameraUser.submitRequest(request2, /* streaming */false);
            fail("Exception expected");
        } catch(ServiceSpecificException e) {
            assertEquals("Expected submitRequest to throw ILLEGAL_ARGUMENT " +
                    "ServiceSpecificException since the target wasn't registered with createStream.",
                    ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode);
        }
    }

    @SmallTest
    public void testSubmitGoodRequest() throws Exception {

        CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true);
        CaptureRequest request = builder.build();

        // Submit valid request twice.
        SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
        SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false);
        assertNotSame("Request IDs should be unique for multiple requests",
                requestInfo1.getRequestId(), requestInfo2.getRequestId());

    }

    @SmallTest
    public void testSubmitStreamingRequest() throws Exception {

        CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true);

        CaptureRequest request = builder.build();

        // Submit valid request once (non-streaming), and another time
        // (streaming)
        SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);

        SubmitInfo requestInfoStreaming = submitCameraRequest(request, /* streaming */true);
        assertNotSame("Request IDs should be unique for multiple requests",
                requestInfo1.getRequestId(),
                requestInfoStreaming.getRequestId());

        try {
            long lastFrameNumber = mCameraUser.cancelRequest(-1);
            fail("Expected exception");
        } catch (ServiceSpecificException e) {
            assertEquals("Invalid request IDs should not be cancellable",
                    ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode);
        }

        try {
            long lastFrameNumber = mCameraUser.cancelRequest(requestInfo1.getRequestId());
            fail("Expected exception");
        } catch (ServiceSpecificException e) {
            assertEquals("Non-streaming request IDs should not be cancellable",
                    ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode);
        }

        long lastFrameNumber = mCameraUser.cancelRequest(requestInfoStreaming.getRequestId());
    }

    @SmallTest
    public void testCameraInfo() throws RemoteException {
        CameraMetadataNative info = mCameraUser.getCameraInfo();

        assertFalse(info.isEmpty());
        assertNotNull(info.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS));
    }

    @SmallTest
    public void testCameraCharacteristics() throws RemoteException {
        CameraMetadataNative info = mUtils.getCameraService().getCameraCharacteristics(mCameraId);

        assertFalse(info.isEmpty());
        assertNotNull(info.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS));
    }

    @SmallTest
    public void testWaitUntilIdle() throws Exception {
        CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true);
        SubmitInfo requestInfoStreaming = submitCameraRequest(builder.build(), /* streaming */true);

        // Test Bad case first: waitUntilIdle when there is active repeating request
        try {
            mCameraUser.waitUntilIdle();
        } catch (ServiceSpecificException e) {
            assertEquals("waitUntilIdle is invalid operation when there is active repeating request",
                    ICameraService.ERROR_INVALID_OPERATION, e.errorCode);
        }

        // Test good case, waitUntilIdle when there is no active repeating request
        long lastFrameNumber = mCameraUser.cancelRequest(requestInfoStreaming.getRequestId());
        mCameraUser.waitUntilIdle();
    }

    @SmallTest
    public void testCaptureResultCallbacks() throws Exception {
        IsMetadataNotEmpty matcher = new IsMetadataNotEmpty();
        CaptureRequest request = createDefaultBuilder(/* needStream */true).build();

        // Test both single request and streaming request.
        verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).times(1)).onResultReceived(
                argThat(matcher),
                any(CaptureResultExtras.class),
                any(PhysicalCaptureResultInfo[].class));

        verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED))
                .onResultReceived(
                        argThat(matcher),
                        any(CaptureResultExtras.class),
                        any(PhysicalCaptureResultInfo[].class));
    }

    @SmallTest
    public void testCaptureStartedCallbacks() throws Exception {
        CaptureRequest request = createDefaultBuilder(/* needStream */true).build();

        ArgumentCaptor<Long> timestamps = ArgumentCaptor.forClass(Long.class);

        // Test both single request and streaming request.
        SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
        verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).times(1)).onCaptureStarted(
                any(CaptureResultExtras.class),
                anyLong());

        SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true);
        verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED))
                .onCaptureStarted(
                        any(CaptureResultExtras.class),
                        timestamps.capture());

        long timestamp = 0; // All timestamps should be larger than 0.
        for (Long nextTimestamp : timestamps.getAllValues()) {
            Log.v(TAG, "next t: " + nextTimestamp + " current t: " + timestamp);
            assertTrue("Captures are out of order", timestamp < nextTimestamp);
            timestamp = nextTimestamp;
        }
    }

    @SmallTest
    public void testIdleCallback() throws Exception {
        int status;
        CaptureRequest request = createDefaultBuilder(/* needStream */true).build();

        // Try streaming
        SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true);

        // Wait a bit to fill up the queue
        SystemClock.sleep(WAIT_FOR_WORK_MS);

        // Cancel and make sure we eventually quiesce
        long lastFrameNumber = mCameraUser.cancelRequest(streamingInfo.getRequestId());

        verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(1)).onDeviceIdle();

        // Submit a few capture requests
        SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
        SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false);
        SubmitInfo requestInfo3 = submitCameraRequest(request, /* streaming */false);
        SubmitInfo requestInfo4 = submitCameraRequest(request, /* streaming */false);
        SubmitInfo requestInfo5 = submitCameraRequest(request, /* streaming */false);

        // And wait for more idle
        verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(2)).onDeviceIdle();

    }

    @SmallTest
    public void testFlush() throws Exception {
        int status;

        // Initial flush should work
        long lastFrameNumber = mCameraUser.flush();

        // Then set up a stream
        CaptureRequest request = createDefaultBuilder(/* needStream */true).build();

        // Flush should still be a no-op, really
        lastFrameNumber = mCameraUser.flush();

        // Submit a few capture requests
        SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
        SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false);
        SubmitInfo requestInfo3 = submitCameraRequest(request, /* streaming */false);
        SubmitInfo requestInfo4 = submitCameraRequest(request, /* streaming */false);
        SubmitInfo requestInfo5 = submitCameraRequest(request, /* streaming */false);

        // Then flush and wait for idle
        lastFrameNumber = mCameraUser.flush();

        verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(1)).onDeviceIdle();

        // Now a streaming request
        SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true);

        // Wait a bit to fill up the queue
        SystemClock.sleep(WAIT_FOR_WORK_MS);

        // Then flush and wait for the idle callback
        lastFrameNumber = mCameraUser.flush();

        verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(2)).onDeviceIdle();

        // TODO: When errors are hooked up, count that errors + successful
        // requests equal to 5.
    }
}
