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

        verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED))
                .onResultReceived(
                        argThat(matcher),
                        any(CaptureResultExtras.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.
    }
}
