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

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

import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCaptureSession.CaptureListener;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.util.Size;
import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureListener;
import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
import android.util.Log;
import android.util.Range;

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

import static org.mockito.Mockito.*;

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

/**
 * CameraDevice preview test by using SurfaceView.
 */
public class SurfaceViewPreviewTest extends Camera2SurfaceViewTestCase {
    private static final String TAG = "SurfaceViewPreviewTest";
    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
    private static final int FRAME_TIMEOUT_MS = 1000;
    private static final int NUM_FRAMES_VERIFIED = 30;
    private static final int NUM_TEST_PATTERN_FRAMES_VERIFIED = 60;
    private static final float FRAME_DURATION_ERROR_MARGIN = 0.005f; // 0.5 percent error margin.

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

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

    /**
     * Test all supported preview sizes for each camera device.
     * <p>
     * For the first  {@link #NUM_FRAMES_VERIFIED}  of capture results,
     * the {@link CaptureListener} callback availability and the capture timestamp
     * (monotonically increasing) ordering are verified.
     * </p>
     */
    public void testCameraPreview() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                Log.i(TAG, "Testing preview for Camera " + mCameraIds[i]);
                openDevice(mCameraIds[i]);

                previewTestByCamera();
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Basic test pattern mode preview.
     * <p>
     * Only test the test pattern preview and capture result, the image buffer
     * is not validated.
     * </p>
     */
    public void testBasicTestPatternPreview() throws Exception{
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                Log.i(TAG, "Testing preview for Camera " + mCameraIds[i]);
                openDevice(mCameraIds[i]);

                previewTestPatternTestByCamera();
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE} for preview, validate the preview
     * frame duration and exposure time.
     */
    public void testPreviewFpsRange() throws Exception {
        for (String id : mCameraIds) {
            try {
                openDevice(id);

                previewFpsRangeTestByCamera();
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test preview fps range for all supported ranges. The exposure time are frame duration are
     * validated.
     */
    private void previewFpsRangeTestByCamera() throws Exception {
        final int FPS_RANGE_SIZE = 2;
        Size maxPreviewSz = mOrderedPreviewSizes.get(0);
        Range<Integer>[] fpsRanges = mStaticInfo.getAeAvailableTargetFpsRangesChecked();
        boolean antiBandingOffIsSupported = mStaticInfo.isAntiBandingOffModeSupported();
        Range<Integer> fpsRange;
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        SimpleCaptureListener resultListener = new SimpleCaptureListener();
        startPreview(requestBuilder, maxPreviewSz, resultListener);

        for (int i = 0; i < fpsRanges.length; i += 1) {
            fpsRange = fpsRanges[i];

            requestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange);
            // Turn off auto antibanding to avoid exposure time and frame duration interference
            // from antibanding algorithm.
            if (antiBandingOffIsSupported) {
                requestBuilder.set(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE,
                        CaptureRequest.CONTROL_AE_ANTIBANDING_MODE_OFF);
            } else {
                // The device doesn't implement the OFF mode, test continues. It need make sure
                // that the antibanding algorithm doesn't interfere with the fps range control.
                Log.i(TAG, "OFF antibanding mode is not supported, the camera device output must" +
                        " satisfy the specified fps range regardless of its current antibanding" +
                        " mode");
            }

            resultListener = new SimpleCaptureListener();
            mSession.setRepeatingRequest(requestBuilder.build(), resultListener, mHandler);

            verifyPreviewTargetFpsRange(resultListener, NUM_FRAMES_VERIFIED, fpsRange,
                    maxPreviewSz);
        }

        stopPreview();
    }

    private void verifyPreviewTargetFpsRange(SimpleCaptureListener resultListener,
            int numFramesVerified, Range<Integer> fpsRange, Size previewSz) {
        CaptureResult result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
        List<Integer> capabilities = mStaticInfo.getAvailableCapabilitiesChecked();

        if (capabilities.contains(CaptureRequest.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
            long frameDuration = getValueNotNull(result, CaptureResult.SENSOR_FRAME_DURATION);
            long[] frameDurationRange =
                    new long[]{(long) (1e9 / fpsRange.getUpper()), (long) (1e9 / fpsRange.getLower())};
            mCollector.expectInRange(
                    "Frame duration must be in the range of " + Arrays.toString(frameDurationRange),
                    frameDuration, (long) (frameDurationRange[0] * (1 - FRAME_DURATION_ERROR_MARGIN)),
                    (long) (frameDurationRange[1] * (1 + FRAME_DURATION_ERROR_MARGIN)));
            long expTime = getValueNotNull(result, CaptureResult.SENSOR_EXPOSURE_TIME);
            mCollector.expectTrue(String.format("Exposure time %d must be no larger than frame"
                    + "duration %d", expTime, frameDuration), expTime <= frameDuration);

            Long minFrameDuration = mMinPreviewFrameDurationMap.get(previewSz);
            boolean findDuration = mCollector.expectTrue("Unable to find minFrameDuration for size "
                    + previewSz.toString(), minFrameDuration != null);
            if (findDuration) {
                mCollector.expectTrue("Frame duration " + frameDuration + " must be no smaller than"
                        + " minFrameDuration " + minFrameDuration, frameDuration >= minFrameDuration);
            }
        } else {
            Log.i(TAG, "verifyPreviewTargetFpsRange - MANUAL_SENSOR control is not supported," +
                    " skipping duration and exposure time check.");
        }
    }

    /**
     * Test all supported preview sizes for a camera device
     *
     * @throws Exception
     */
    private void previewTestByCamera() throws Exception {
        List<Size> previewSizes = getSupportedPreviewSizes(
                mCamera.getId(), mCameraManager, PREVIEW_SIZE_BOUND);

        for (final Size sz : previewSizes) {
            if (VERBOSE) {
                Log.v(TAG, "Testing camera preview size: " + sz.toString());
            }

            // TODO: vary the different settings like crop region to cover more cases.
            CaptureRequest.Builder requestBuilder =
                    mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            CaptureListener mockCaptureListener =
                    mock(CameraCaptureSession.CaptureListener.class);

            startPreview(requestBuilder, sz, mockCaptureListener);
            verifyCaptureResults(mSession, mockCaptureListener, NUM_FRAMES_VERIFIED,
                    NUM_FRAMES_VERIFIED * FRAME_TIMEOUT_MS);
            stopPreview();
        }
    }

    private void previewTestPatternTestByCamera() throws Exception {
        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
        int[] testPatternModes = mStaticInfo.getAvailableTestPatternModesChecked();
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        CaptureListener mockCaptureListener;

        final int[] TEST_PATTERN_DATA = {0, 0xFFFFFFFF, 0xFFFFFFFF, 0}; // G:100%, RB:0.
        for (int mode : testPatternModes) {
            if (VERBOSE) {
                Log.v(TAG, "Test pattern mode: " + mode);
            }
            requestBuilder.set(CaptureRequest.SENSOR_TEST_PATTERN_MODE, mode);
            if (mode == CaptureRequest.SENSOR_TEST_PATTERN_MODE_SOLID_COLOR) {
                // Assign color pattern to SENSOR_TEST_PATTERN_MODE_DATA
                requestBuilder.set(CaptureRequest.SENSOR_TEST_PATTERN_DATA, TEST_PATTERN_DATA);
            }
            mockCaptureListener = mock(CaptureListener.class);
            startPreview(requestBuilder, maxPreviewSize, mockCaptureListener);
            verifyCaptureResults(mSession, mockCaptureListener, NUM_TEST_PATTERN_FRAMES_VERIFIED,
                    NUM_TEST_PATTERN_FRAMES_VERIFIED * FRAME_TIMEOUT_MS);
        }

        stopPreview();
    }

    private class IsCaptureResultValid extends ArgumentMatcher<TotalCaptureResult> {
        @Override
        public boolean matches(Object obj) {
            TotalCaptureResult result = (TotalCaptureResult)obj;
            Long timeStamp = result.get(CaptureResult.SENSOR_TIMESTAMP);
            if (timeStamp != null && timeStamp.longValue() > 0L) {
                return true;
            }
            return false;
        }
    }

    private void verifyCaptureResults(
            CameraCaptureSession session,
            CaptureListener mockListener,
            int expectResultCount,
            int timeOutMs) {
        // Should receive expected number of onCaptureStarted callbacks.
        ArgumentCaptor<Long> timestamps = ArgumentCaptor.forClass(Long.class);
        verify(mockListener,
                timeout(timeOutMs).atLeast(expectResultCount))
                        .onCaptureStarted(
                                eq(session),
                                isA(CaptureRequest.class),
                                timestamps.capture());

        // Validate timestamps: all timestamps should be larger than 0 and monotonically increase.
        long timestamp = 0;
        for (Long nextTimestamp : timestamps.getAllValues()) {
            assertNotNull("Next timestamp is null!", nextTimestamp);
            assertTrue("Captures are out of order", timestamp < nextTimestamp);
            timestamp = nextTimestamp;
        }

        // Should receive expected number of capture results.
        verify(mockListener,
                timeout(timeOutMs).atLeast(expectResultCount))
                        .onCaptureCompleted(
                                eq(session),
                                isA(CaptureRequest.class),
                                argThat(new IsCaptureResultValid()));

        // Should not receive any capture failed callbacks.
        verify(mockListener, never())
                        .onCaptureFailed(
                                eq(session),
                                isA(CaptureRequest.class),
                                isA(CaptureFailure.class));
    }

}
