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

import android.graphics.Rect;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.os.Handler;
import android.util.Log;
import android.view.Surface;

import com.android.ex.camera2.pos.AutoFocusStateMachine;
import com.android.ex.camera2.pos.AutoFocusStateMachine.AutoFocusStateListener;

/**
 * A focuser utility class to assist camera to do auto focus.
 * <p>
 * This class need create repeating request and single request to do auto focus.
 * The repeating request is used to get the auto focus states; the single
 * request is used to trigger the auto focus. This class assumes the camera device
 * supports auto-focus. Don't use this class if the camera device doesn't have focuser
 * unit.
 * </p>
 */
public class Camera2Focuser implements AutoFocusStateListener {
    private static final String TAG = "Focuser";
    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);

    private final AutoFocusStateMachine mAutoFocus = new AutoFocusStateMachine(this);
    private final Handler mHandler;
    private final AutoFocusListener mAutoFocusListener;
    private final CameraDevice mCamera;
    private final CameraCaptureSession mSession;
    private final Surface mRequestSurface;
    private final StaticMetadata mStaticInfo;

    private int mAfRun = 0;
    private MeteringRectangle[] mAfRegions;
    private boolean mLocked = false;
    private boolean mSuccess = false;
    private CaptureRequest.Builder mRepeatingBuilder;

    /**
     * The callback interface to notify auto focus result.
     */
    public interface AutoFocusListener {
        /**
         * This callback is called when auto focus completes and locked.
         *
         * @param success true if focus was successful, false if otherwise
         */
        void onAutoFocusLocked(boolean success);
    }

    /**
     * Construct a focuser object, with given capture requestSurface, listener
     * and handler.
     * <p>
     * The focuser object will use camera and requestSurface to submit capture
     * request and receive focus state changes. The {@link AutoFocusListener} is
     * used to notify the auto focus callback.
     * </p>
     *
     * @param camera The camera device associated with this focuser
     * @param session The camera capture session associated with this focuser
     * @param requestSurface The surface to issue the capture request with
     * @param listener The auto focus listener to notify AF result
     * @param staticInfo The CameraCharacteristics of the camera device
     * @param handler The handler used to post auto focus callbacks
     * @throws CameraAccessException
     */
    public Camera2Focuser(CameraDevice camera, CameraCaptureSession session, Surface requestSurface,
            AutoFocusListener listener, CameraCharacteristics staticInfo, Handler handler)
            throws CameraAccessException {
        if (camera == null) {
            throw new IllegalArgumentException("camera must not be null");
        }
        if (session == null) {
            throw new IllegalArgumentException("session must not be null");
        }
        if (listener == null) {
            throw new IllegalArgumentException("listener must not be null");
        }
        if (handler == null) {
            throw new IllegalArgumentException("handler must not be null");
        }
        if (requestSurface == null) {
            throw new IllegalArgumentException("requestSurface must not be null");
        }
        if (staticInfo == null) {
            throw new IllegalArgumentException("staticInfo must not be null");
        }

        mCamera = camera;
        mSession = session;
        mRequestSurface = requestSurface;
        mAutoFocusListener = listener;
        mStaticInfo = new StaticMetadata(staticInfo,
                StaticMetadata.CheckLevel.ASSERT, /*collector*/null);
        mHandler = handler;

        if (!mStaticInfo.hasFocuser()) {
            throw new IllegalArgumentException("this camera doesn't have a focuser");
        }

        /**
         * Begin by always being in passive auto focus.
         */
        cancelAutoFocus();
    }

    @Override
    public synchronized void onAutoFocusSuccess(CaptureResult result, boolean locked) {
        mSuccess = true;
        mLocked = locked;

        if (locked) {
            dispatchAutoFocusStatusLocked(/*success*/true);
        }
    }

    @Override
    public synchronized void onAutoFocusFail(CaptureResult result, boolean locked) {
        mSuccess = false;
        mLocked = locked;

        if (locked) {
            dispatchAutoFocusStatusLocked(/*success*/false);
        }
    }

    @Override
    public synchronized void onAutoFocusScan(CaptureResult result) {
        mSuccess = false;
        mLocked = false;
    }

    @Override
    public synchronized void onAutoFocusInactive(CaptureResult result) {
        mSuccess = false;
        mLocked = false;
    }

    /**
     * Start a active auto focus scan based on the given regions.
     *
     * <p>This is usually used for touch for focus, it can make the auto-focus converge based
     * on some particular region aggressively. But it is usually slow as a full active scan
     * is initiated. After the auto focus is converged, the {@link cancelAutoFocus} must be called
     * to resume the continuous auto-focus.</p>
     *
     * @param afRegions The AF regions used by focuser auto focus, full active
     * array size is used if afRegions is null.
     * @throws CameraAccessException
     */
    public synchronized void touchForAutoFocus(MeteringRectangle[] afRegions)
            throws CameraAccessException {
        startAutoFocusLocked(/*active*/true, afRegions);
    }

    /**
     * Start auto focus scan.
     * <p>
     * Start an auto focus scan if it was not done yet. If AF passively focused,
     * lock it. If AF is already locked, return. Otherwise, initiate a full
     * active scan. This is suitable for still capture: focus should need to be
     * accurate, but the AF latency also need to be as short as possible.
     * </p>
     *
     * @param afRegions The AF regions used by focuser auto focus, full active
     *            array size is used if afRegions is null.
     * @throws CameraAccessException
     */
    public synchronized void startAutoFocus(MeteringRectangle[] afRegions)
            throws CameraAccessException {
        startAutoFocusLocked(/*forceActive*/false, afRegions);
    }

    /**
     * Cancel ongoing auto focus, unlock the auto-focus if it was locked, and
     * resume to passive continuous auto focus.
     *
     * @throws CameraAccessException
     */
    public synchronized void cancelAutoFocus() throws CameraAccessException {
        mSuccess = false;
        mLocked = false;

        // reset the AF regions:
        setAfRegions(null);

        // Create request builders, the af regions are automatically updated.
        mRepeatingBuilder = createRequestBuilder();
        CaptureRequest.Builder requestBuilder = createRequestBuilder();
        mAutoFocus.setPassiveAutoFocus(/*picture*/true, mRepeatingBuilder);
        mAutoFocus.unlockAutoFocus(mRepeatingBuilder, requestBuilder);
        CaptureCallback listener = createCaptureListener();
        mSession.setRepeatingRequest(mRepeatingBuilder.build(), listener, mHandler);
        mSession.capture(requestBuilder.build(), listener, mHandler);
    }

    /**
     * Get current AF mode.
     * @return current AF mode
     * @throws IllegalStateException if there auto focus is not running.
     */
    public synchronized int getCurrentAfMode() {
        if (mRepeatingBuilder == null) {
            throw new IllegalStateException("Auto focus is not running, unable to get AF mode");
        }

        return mRepeatingBuilder.get(CaptureRequest.CONTROL_AF_MODE);
    }

    private void startAutoFocusLocked(
            boolean forceActive, MeteringRectangle[] afRegions) throws CameraAccessException {

        setAfRegions(afRegions);
        mAfRun++;

        // Create request builders, the af regions are automatically updated.
        mRepeatingBuilder = createRequestBuilder();
        CaptureRequest.Builder requestBuilder = createRequestBuilder();
        if (forceActive) {
            startAutoFocusFullActiveLocked();
        } else {
            // Not forcing a full active scan. If AF passively focused, lock it. If AF is already
            // locked, return. Otherwise, initiate a full active scan.
            if (mSuccess && mLocked) {
                dispatchAutoFocusStatusLocked(/*success*/true);
                return;
            } else if (mSuccess) {
                mAutoFocus.lockAutoFocus(mRepeatingBuilder, requestBuilder);
                CaptureCallback listener = createCaptureListener();
                mSession.setRepeatingRequest(mRepeatingBuilder.build(), listener, mHandler);
                mSession.capture(requestBuilder.build(), listener, mHandler);
            } else {
                startAutoFocusFullActiveLocked();
            }
        }
    }

    private void startAutoFocusFullActiveLocked() throws CameraAccessException {
        // Create request builders, the af regions are automatically updated.
        mRepeatingBuilder = createRequestBuilder();
        CaptureRequest.Builder requestBuilder = createRequestBuilder();
        mAutoFocus.setActiveAutoFocus(mRepeatingBuilder, requestBuilder);
        if (mRepeatingBuilder.get(CaptureRequest.CONTROL_AF_TRIGGER)
                != CaptureRequest.CONTROL_AF_TRIGGER_IDLE) {
            throw new AssertionError("Wrong trigger set in repeating request");
        }
        if (requestBuilder.get(CaptureRequest.CONTROL_AF_TRIGGER)
                != CaptureRequest.CONTROL_AF_TRIGGER_START) {
            throw new AssertionError("Wrong trigger set in queued request");
        }
        mAutoFocus.resetState();

        CaptureCallback listener = createCaptureListener();
        mSession.setRepeatingRequest(mRepeatingBuilder.build(), listener, mHandler);
        mSession.capture(requestBuilder.build(), listener, mHandler);
    }

    private void dispatchAutoFocusStatusLocked(final boolean success) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                mAutoFocusListener.onAutoFocusLocked(success);
            }
        });
    }

    /**
     * Create request builder, set the af regions.
     * @throws CameraAccessException
     */
    private CaptureRequest.Builder createRequestBuilder() throws CameraAccessException {
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

        requestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, mAfRegions);
        requestBuilder.addTarget(mRequestSurface);

        return requestBuilder;
    }

    /**
     * Set AF regions, fall back to default region if afRegions is null.
     *
     * @param afRegions The AF regions to set
     * @throws IllegalArgumentException if the region is malformed (length is 0).
     */
    private void setAfRegions(MeteringRectangle[] afRegions) {
        if (afRegions == null) {
            setDefaultAfRegions();
            return;
        }
        // Throw IAE if AF regions are malformed.
        if (afRegions.length == 0) {
            throw new IllegalArgumentException("afRegions is malformed, length: 0");
        }

        mAfRegions = afRegions;
    }

    /**
     * Set default AF region to full active array size.
     */
    private void setDefaultAfRegions() {
        // Initialize AF regions with all zeros, meaning that it is up to camera device to device
        // the regions used by AF.
        mAfRegions = new MeteringRectangle[] {
                new MeteringRectangle(0, 0, 0, 0, MeteringRectangle.METERING_WEIGHT_DONT_CARE)};
    }
    private CaptureCallback createCaptureListener() {

        int thisAfRun;
        synchronized (this) {
            thisAfRun = mAfRun;
        }

        final int finalAfRun = thisAfRun;

        return new CaptureCallback() {
            private long mLatestFrameCount = -1;

            @Override
            public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request,
                    CaptureResult result) {
                // In case of a partial result, send to focuser if necessary
                // 3A fields are present
                if (result.get(CaptureResult.CONTROL_AF_STATE) != null &&
                        result.get(CaptureResult.CONTROL_AF_MODE) != null) {
                    if (VERBOSE) {
                        Log.v(TAG, "Focuser - got early AF state");
                    }

                    dispatchToFocuser(result);
                }
            }

            @Override
            public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
                    TotalCaptureResult result) {
                    dispatchToFocuser(result);
            }

            private void dispatchToFocuser(CaptureResult result) {
                int afRun;
                synchronized (Camera2Focuser.this) {
                    // In case of partial results, don't send AF update twice
                    long frameCount = result.getFrameNumber();
                    if (frameCount <= mLatestFrameCount) return;
                    mLatestFrameCount = frameCount;

                    afRun = mAfRun;
                }

                if (afRun != finalAfRun) {
                    if (VERBOSE) {
                        Log.w(TAG,
                                "onCaptureCompleted - Ignoring results from previous AF run "
                                + finalAfRun);
                    }
                    return;
                }

                mAutoFocus.onCaptureCompleted(result);
            }
        };
    }
}
