/*
 * 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.graphics.ImageFormat;
import android.view.Surface;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
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.SimpleCaptureCallback;
import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
import android.util.Log;
import android.util.Pair;
import android.util.Range;

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

import static org.mockito.Mockito.*;

import java.util.ArrayList;
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 CaptureCallback} 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]);
                if (!mStaticInfo.isColorOutputSupported()) {
                    Log.i(TAG, "Camera " + mCameraIds[i] +
                            " does not support color outputs, skipping");
                    continue;
                }
                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]);
                if (!mStaticInfo.isColorOutputSupported()) {
                    Log.i(TAG, "Camera " + mCameraIds[i] +
                            " does not support color outputs, skipping");
                    continue;
                }
                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);
                if (!mStaticInfo.isColorOutputSupported()) {
                    Log.i(TAG, "Camera " + id + " does not support color outputs, skipping");
                    continue;
                }
                previewFpsRangeTestByCamera();
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test to verify the {@link CameraCaptureSession#prepare} method works correctly, and has the
     * expected effects on performance.
     *
     * - Ensure that prepare() results in onSurfacePrepared() being invoked
     * - Ensure that prepare() does not cause preview glitches while operating
     * - Ensure that starting to use a newly-prepared output does not cause additional
     *   preview glitches to occur
     */
    public void testPreparePerformance() throws Throwable {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i]);
                if (!mStaticInfo.isColorOutputSupported()) {
                    Log.i(TAG, "Camera " + mCameraIds[i] +
                            " does not support color outputs, skipping");
                    continue;
                }
                preparePerformanceTestByCamera(mCameraIds[i]);
            }
            finally {
                closeDevice();
            }
        }
    }

    private void preparePerformanceTestByCamera(String cameraId) throws Exception {
        final int MAX_IMAGES_TO_PREPARE = 10;
        final int UNKNOWN_LATENCY_RESULT_WAIT = 5;
        final int MAX_RESULTS_TO_WAIT = 10;
        final int FRAMES_FOR_AVERAGING = 100;
        final int PREPARE_TIMEOUT_MS = 10000; // 10 s
        final float PREPARE_FRAME_RATE_BOUNDS = 0.05f; // fraction allowed difference
        final float PREPARE_PEAK_RATE_BOUNDS = 0.5f; // fraction allowed difference

        Size maxYuvSize = getSupportedPreviewSizes(cameraId, mCameraManager, null).get(0);
        Size maxPreviewSize = mOrderedPreviewSizes.get(0);

        // Don't need image data, just drop it right away to minimize overhead
        ImageDropperListener imageListener = new ImageDropperListener();

        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();

        CaptureRequest.Builder previewRequest =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

        // Configure outputs and session

        updatePreviewSurface(maxPreviewSize);

        createImageReader(maxYuvSize, ImageFormat.YUV_420_888, MAX_IMAGES_TO_PREPARE, imageListener);

        List<Surface> outputSurfaces = new ArrayList<Surface>();
        outputSurfaces.add(mPreviewSurface);
        outputSurfaces.add(mReaderSurface);

        CameraCaptureSession.StateCallback mockSessionListener =
                mock(CameraCaptureSession.StateCallback.class);

        mSession = configureCameraSession(mCamera, outputSurfaces, mockSessionListener, mHandler);

        previewRequest.addTarget(mPreviewSurface);
        Range<Integer> maxFpsTarget = mStaticInfo.getAeMaxTargetFpsRange();
        previewRequest.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, maxFpsTarget);

        mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler);

        // Converge AE
        waitForAeStable(resultListener, UNKNOWN_LATENCY_RESULT_WAIT);

        if (mStaticInfo.isAeLockSupported()) {
            // Lock AE if possible to improve stability
            previewRequest.set(CaptureRequest.CONTROL_AE_LOCK, true);
            mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler);
            if (mStaticInfo.isHardwareLevelLimitedOrBetter()) {
                // Legacy mode doesn't output AE state
                waitForResultValue(resultListener, CaptureResult.CONTROL_AE_STATE,
                        CaptureResult.CONTROL_AE_STATE_LOCKED, MAX_RESULTS_TO_WAIT);
            }
        }

        // Measure frame rate for a bit
        Pair<Long, Long> frameDurationStats =
                measureMeanFrameInterval(resultListener, FRAMES_FOR_AVERAGING, /*prevTimestamp*/ 0);

        Log.i(TAG, String.format("Frame interval avg during normal preview: %f ms, peak %f ms",
                        frameDurationStats.first / 1e6, frameDurationStats.second / 1e6));

        // Drain results, do prepare
        resultListener.drain();

        mSession.prepare(mReaderSurface);

        verify(mockSessionListener,
                timeout(PREPARE_TIMEOUT_MS).times(1)).
                onSurfacePrepared(eq(mSession), eq(mReaderSurface));

        // Calculate frame rate during prepare

        int resultsReceived = (int) resultListener.getTotalNumFrames();
        if (resultsReceived > 2) {
            // Only verify frame rate if there are a couple of results
            Pair<Long, Long> whilePreparingFrameDurationStats =
                    measureMeanFrameInterval(resultListener, resultsReceived, /*prevTimestamp*/ 0);

            Log.i(TAG, String.format("Frame interval during prepare avg: %f ms, peak %f ms",
                            whilePreparingFrameDurationStats.first / 1e6,
                            whilePreparingFrameDurationStats.second / 1e6));

            if (mStaticInfo.isHardwareLevelLimitedOrBetter()) {
                mCollector.expectTrue(
                    String.format("Camera %s: Preview peak frame interval affected by prepare " +
                            "call: preview avg frame duration: %f ms, peak during prepare: %f ms",
                            cameraId,
                            frameDurationStats.first / 1e6,
                            whilePreparingFrameDurationStats.second / 1e6),
                    (whilePreparingFrameDurationStats.second <=
                            frameDurationStats.first * (1 + PREPARE_PEAK_RATE_BOUNDS)));
                mCollector.expectTrue(
                    String.format("Camera %s: Preview average frame interval affected by prepare " +
                            "call: preview avg frame duration: %f ms, during prepare: %f ms",
                            cameraId,
                            frameDurationStats.first / 1e6,
                            whilePreparingFrameDurationStats.first / 1e6),
                    (whilePreparingFrameDurationStats.first <=
                            frameDurationStats.first * (1 + PREPARE_FRAME_RATE_BOUNDS)));
            }
        }

        resultListener.drain();

        // Get at least one more preview result without prepared target
        CaptureResult result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
        long prevTimestamp = result.get(CaptureResult.SENSOR_TIMESTAMP);

        // Now use the prepared stream and ensure there are no hiccups from using it
        previewRequest.addTarget(mReaderSurface);

        mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler);

        Pair<Long, Long> preparedFrameDurationStats =
                measureMeanFrameInterval(resultListener, MAX_IMAGES_TO_PREPARE*2, prevTimestamp);

        Log.i(TAG, String.format("Frame interval with prepared stream added avg: %f ms, peak %f ms",
                        preparedFrameDurationStats.first / 1e6,
                        preparedFrameDurationStats.second / 1e6));

        if (mStaticInfo.isHardwareLevelLimitedOrBetter()) {
            mCollector.expectTrue(
                String.format("Camera %s: Preview peak frame interval affected by use of new " +
                        " stream: preview avg frame duration: %f ms, peak with new stream: %f ms",
                        cameraId,
                        frameDurationStats.first / 1e6, preparedFrameDurationStats.second / 1e6),
                (preparedFrameDurationStats.second <=
                        frameDurationStats.first * (1 + PREPARE_PEAK_RATE_BOUNDS)));
            mCollector.expectTrue(
                String.format("Camera %s: Preview average frame interval affected by use of new " +
                        "stream: preview avg frame duration: %f ms, with new stream: %f ms",
                        cameraId,
                        frameDurationStats.first / 1e6, preparedFrameDurationStats.first / 1e6),
                (preparedFrameDurationStats.first <=
                        frameDurationStats.first * (1 + PREPARE_FRAME_RATE_BOUNDS)));
        }
    }

    /**
     * Measure the inter-frame interval based on SENSOR_TIMESTAMP for frameCount frames from the
     * provided capture listener.  If prevTimestamp is positive, it is used for the first interval
     * calculation; otherwise, the first result is used to establish the starting time.
     *
     * Returns the mean interval in the first pair entry, and the largest interval in the second
     * pair entry
     */
    Pair<Long, Long> measureMeanFrameInterval(SimpleCaptureCallback resultListener, int frameCount,
            long prevTimestamp) throws Exception {
        long summedIntervals = 0;
        long maxInterval = 0;
        int measurementCount = frameCount - ((prevTimestamp > 0) ? 0 : 1);

        for (int i = 0; i < frameCount; i++) {
            CaptureResult result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
            long timestamp = result.get(CaptureResult.SENSOR_TIMESTAMP);
            if (prevTimestamp > 0) {
                long interval = timestamp - prevTimestamp;
                if (interval > maxInterval) maxInterval = interval;
                summedIntervals += interval;
            }
            prevTimestamp = timestamp;
        }
        return new Pair<Long, Long>(summedIntervals / measurementCount, maxInterval);
    }


    /**
     * 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);
        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
        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 SimpleCaptureCallback();
            mSession.setRepeatingRequest(requestBuilder.build(), resultListener, mHandler);

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

        stopPreview();
    }

    private void verifyPreviewTargetFpsRange(SimpleCaptureCallback 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);
            CaptureCallback mockCaptureCallback =
                    mock(CameraCaptureSession.CaptureCallback.class);

            startPreview(requestBuilder, sz, mockCaptureCallback);
            verifyCaptureResults(mSession, mockCaptureCallback, 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);
        CaptureCallback mockCaptureCallback;

        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);
            }
            mockCaptureCallback = mock(CaptureCallback.class);
            startPreview(requestBuilder, maxPreviewSize, mockCaptureCallback);
            verifyCaptureResults(mSession, mockCaptureCallback, 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,
            CaptureCallback mockListener,
            int expectResultCount,
            int timeOutMs) {
        // Should receive expected number of onCaptureStarted callbacks.
        ArgumentCaptor<Long> timestamps = ArgumentCaptor.forClass(Long.class);
        ArgumentCaptor<Long> frameNumbers = ArgumentCaptor.forClass(Long.class);
        verify(mockListener,
                timeout(timeOutMs).atLeast(expectResultCount))
                        .onCaptureStarted(
                                eq(session),
                                isA(CaptureRequest.class),
                                timestamps.capture(),
                                frameNumbers.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;
        }

        // Validate framenumbers: all framenumbers should be consecutive and positive
        long frameNumber = -1;
        for (Long nextFrameNumber : frameNumbers.getAllValues()) {
            assertNotNull("Next frame number is null!", nextFrameNumber);
            assertTrue("Captures are out of order",
                    (frameNumber == -1) || (frameNumber + 1 == nextFrameNumber));
            frameNumber = nextFrameNumber;
        }

        // 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));
    }

}
