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

import android.graphics.Rect;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.legacy.ParameterUtils.WeightedRectangle;
import android.hardware.camera2.legacy.ParameterUtils.ZoomData;
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.utils.ListUtils;
import android.hardware.camera2.utils.ParamsUtils;
import android.util.Log;
import android.util.Size;

import java.util.ArrayList;
import java.util.List;

import static android.hardware.camera2.CaptureResult.*;

/**
 * Provide legacy-specific implementations of camera2 CaptureResult for legacy devices.
 */
@SuppressWarnings("deprecation")
public class LegacyResultMapper {
    private static final String TAG = "LegacyResultMapper";
    private static final boolean DEBUG = false;

    private LegacyRequest mCachedRequest = null;
    private CameraMetadataNative mCachedResult = null;

    /**
     * Generate capture result metadata from the legacy camera request.
     *
     * <p>This method caches and reuses the result from the previous call to this method if
     * the {@code parameters} of the subsequent {@link LegacyRequest} passed to this method
     * have not changed.</p>
     *
     * @param legacyRequest a non-{@code null} legacy request containing the latest parameters
     * @param timestamp the timestamp to use for this result in nanoseconds.
     *
     * @return {@link CameraMetadataNative} object containing result metadata.
     */
    public CameraMetadataNative cachedConvertResultMetadata(
            LegacyRequest legacyRequest, long timestamp) {
        CameraMetadataNative result;
        boolean cached;

        /*
         * Attempt to look up the result from the cache if the parameters haven't changed
         */
        if (mCachedRequest != null &&
                legacyRequest.parameters.same(mCachedRequest.parameters) &&
                legacyRequest.captureRequest.equals(mCachedRequest.captureRequest)) {
            result = new CameraMetadataNative(mCachedResult);
            cached = true;
        } else {
            result = convertResultMetadata(legacyRequest);
            cached = false;

            // Always cache a *copy* of the metadata result,
            // since api2's client side takes ownership of it after it receives a result
            mCachedRequest = legacyRequest;
            mCachedResult = new CameraMetadataNative(result);
        }

        /*
         * Unconditionally set fields that change in every single frame
         */
        {
            // sensor.timestamp
            result.set(SENSOR_TIMESTAMP, timestamp);
        }

        if (DEBUG) {
            Log.v(TAG, "cachedConvertResultMetadata - cached? " + cached +
                    " timestamp = " + timestamp);

            Log.v(TAG, "----- beginning of result dump ------");
            result.dumpToLog();
            Log.v(TAG, "----- end of result dump ------");
        }

        return result;
    }

    /**
     * Generate capture result metadata from the legacy camera request.
     *
     * @param legacyRequest a non-{@code null} legacy request containing the latest parameters
     * @return a {@link CameraMetadataNative} object containing result metadata.
     */
    private static CameraMetadataNative convertResultMetadata(LegacyRequest legacyRequest) {
        CameraCharacteristics characteristics = legacyRequest.characteristics;
        CaptureRequest request = legacyRequest.captureRequest;
        Size previewSize = legacyRequest.previewSize;
        Camera.Parameters params = legacyRequest.parameters;

        CameraMetadataNative result = new CameraMetadataNative();

        Rect activeArraySize = characteristics.get(
                CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
        ZoomData zoomData = ParameterUtils.convertToLegacyZoom(activeArraySize,
                request.get(CaptureRequest.SCALER_CROP_REGION),
                request.get(CaptureRequest.CONTROL_ZOOM_RATIO),
                previewSize, params);

        /*
         * colorCorrection
         */
        // colorCorrection.aberrationMode
        {
            result.set(COLOR_CORRECTION_ABERRATION_MODE,
                    request.get(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE));
        }

        /*
         * control
         */

        /*
         * control.ae*
         */
        mapAe(result, characteristics, request, activeArraySize, zoomData, /*out*/params);

        /*
         * control.af*
         */
        mapAf(result, activeArraySize, zoomData, /*out*/params);

        /*
         * control.awb*
         */
        mapAwb(result, /*out*/params);

        /*
         * control.captureIntent
         */
        {
            int captureIntent = ParamsUtils.getOrDefault(request,
                    CaptureRequest.CONTROL_CAPTURE_INTENT,
                    /*defaultValue*/CaptureRequest.CONTROL_CAPTURE_INTENT_PREVIEW);

            captureIntent = LegacyRequestMapper.filterSupportedCaptureIntent(captureIntent);

            result.set(CONTROL_CAPTURE_INTENT, captureIntent);
        }

        /*
         * control.mode
         */
        {
            int controlMode = ParamsUtils.getOrDefault(request, CaptureRequest.CONTROL_MODE,
                    CONTROL_MODE_AUTO);
            if (controlMode == CaptureResult.CONTROL_MODE_USE_SCENE_MODE) {
                result.set(CONTROL_MODE, CONTROL_MODE_USE_SCENE_MODE);
            } else {
                result.set(CONTROL_MODE, CONTROL_MODE_AUTO);
            }
        }

        /*
         * control.sceneMode
         */
        {
            String legacySceneMode = params.getSceneMode();
            int mode = LegacyMetadataMapper.convertSceneModeFromLegacy(legacySceneMode);
            if (mode != LegacyMetadataMapper.UNKNOWN_MODE) {
                result.set(CaptureResult.CONTROL_SCENE_MODE, mode);
                // In case of SCENE_MODE == FACE_PRIORITY, LegacyFaceDetectMapper will override
                // the result to say SCENE_MODE == FACE_PRIORITY.
            }  else {
                Log.w(TAG, "Unknown scene mode " + legacySceneMode +
                        " returned by camera HAL, setting to disabled.");
                result.set(CaptureResult.CONTROL_SCENE_MODE, CONTROL_SCENE_MODE_DISABLED);
            }
        }

        /*
         * control.effectMode
         */
        {
            String legacyEffectMode = params.getColorEffect();
            int mode = LegacyMetadataMapper.convertEffectModeFromLegacy(legacyEffectMode);
            if (mode != LegacyMetadataMapper.UNKNOWN_MODE) {
                result.set(CaptureResult.CONTROL_EFFECT_MODE, mode);
            } else {
                Log.w(TAG, "Unknown effect mode " + legacyEffectMode +
                        " returned by camera HAL, setting to off.");
                result.set(CaptureResult.CONTROL_EFFECT_MODE, CONTROL_EFFECT_MODE_OFF);
            }
        }

        // control.videoStabilizationMode
        {
            int stabMode =
                    (params.isVideoStabilizationSupported() && params.getVideoStabilization()) ?
                        CONTROL_VIDEO_STABILIZATION_MODE_ON :
                        CONTROL_VIDEO_STABILIZATION_MODE_OFF;
            result.set(CONTROL_VIDEO_STABILIZATION_MODE, stabMode);
        }

        /*
         * flash
         */
        {
            // flash.mode, flash.state mapped in mapAeAndFlashMode
        }

        /*
         * lens
         */
        // lens.focusDistance
        {
            if (Parameters.FOCUS_MODE_INFINITY.equals(params.getFocusMode())) {
                result.set(CaptureResult.LENS_FOCUS_DISTANCE, 0.0f);
            }
        }

        // lens.focalLength
        result.set(CaptureResult.LENS_FOCAL_LENGTH, params.getFocalLength());

        /*
         * request
         */
        // request.pipelineDepth
        result.set(REQUEST_PIPELINE_DEPTH,
                characteristics.get(CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH));

        /*
         * scaler
         */
        mapScaler(result, zoomData, /*out*/params);

        /*
         * sensor
         */
        // sensor.timestamp varies every frame; mapping is done in #cachedConvertResultMetadata
        {
            // Unconditionally no test patterns
            result.set(SENSOR_TEST_PATTERN_MODE, SENSOR_TEST_PATTERN_MODE_OFF);
        }

        /*
         * jpeg
         */
        // jpeg.gpsLocation
        result.set(JPEG_GPS_LOCATION, request.get(CaptureRequest.JPEG_GPS_LOCATION));

        // jpeg.orientation
        result.set(JPEG_ORIENTATION, request.get(CaptureRequest.JPEG_ORIENTATION));

        // jpeg.quality
        result.set(JPEG_QUALITY, (byte) params.getJpegQuality());

        // jpeg.thumbnailQuality
        result.set(JPEG_THUMBNAIL_QUALITY, (byte) params.getJpegThumbnailQuality());

        // jpeg.thumbnailSize
        Camera.Size s = params.getJpegThumbnailSize();
        if (s != null) {
            result.set(JPEG_THUMBNAIL_SIZE, ParameterUtils.convertSize(s));
        } else {
            Log.w(TAG, "Null thumbnail size received from parameters.");
        }

        /*
         * noiseReduction.*
         */
        // noiseReduction.mode
        result.set(NOISE_REDUCTION_MODE, request.get(CaptureRequest.NOISE_REDUCTION_MODE));

        return result;
    }

    private static void mapAe(CameraMetadataNative m,
            CameraCharacteristics characteristics,
            CaptureRequest request, Rect activeArray, ZoomData zoomData, /*out*/Parameters p) {
        // control.aeAntiBandingMode
        {
            int antiBandingMode = LegacyMetadataMapper.convertAntiBandingModeOrDefault(
                    p.getAntibanding());
            m.set(CONTROL_AE_ANTIBANDING_MODE, antiBandingMode);
        }

        // control.aeExposureCompensation
        {
            m.set(CONTROL_AE_EXPOSURE_COMPENSATION, p.getExposureCompensation());
        }

        // control.aeLock
        {
            boolean lock = p.isAutoExposureLockSupported() ? p.getAutoExposureLock() : false;
            m.set(CONTROL_AE_LOCK, lock);
            if (DEBUG) {
                Log.v(TAG,
                        "mapAe - android.control.aeLock = " + lock +
                        ", supported = " + p.isAutoExposureLockSupported());
            }

            Boolean requestLock = request.get(CaptureRequest.CONTROL_AE_LOCK);
            if (requestLock != null && requestLock != lock) {
                Log.w(TAG,
                        "mapAe - android.control.aeLock was requested to " + requestLock +
                        " but resulted in " + lock);
            }
        }

        // control.aeMode, flash.mode, flash.state
        mapAeAndFlashMode(m, characteristics, p);

        // control.aeState
        if (LegacyMetadataMapper.LIE_ABOUT_AE_STATE) {
            // Lie to pass CTS temporarily.
            // TODO: Implement precapture trigger, after which we can report CONVERGED ourselves
            m.set(CONTROL_AE_STATE, CONTROL_AE_STATE_CONVERGED);
        }

        // control.aeRegions
        if (p.getMaxNumMeteringAreas() > 0) {
            if (DEBUG) {
                String meteringAreas = p.get("metering-areas");
                Log.v(TAG, "mapAe - parameter dump; metering-areas: " + meteringAreas);
            }

            MeteringRectangle[] meteringRectArray = getMeteringRectangles(activeArray,
                    zoomData, p.getMeteringAreas(), "AE");

            m.set(CONTROL_AE_REGIONS, meteringRectArray);
        }

    }

    private static void mapAf(CameraMetadataNative m,
            Rect activeArray, ZoomData zoomData, Camera.Parameters p) {
        // control.afMode
        m.set(CaptureResult.CONTROL_AF_MODE, convertLegacyAfMode(p.getFocusMode()));

        // control.afRegions
        if (p.getMaxNumFocusAreas() > 0) {
            if (DEBUG) {
                String focusAreas = p.get("focus-areas");
                Log.v(TAG, "mapAe - parameter dump; focus-areas: " + focusAreas);
            }

            MeteringRectangle[] meteringRectArray = getMeteringRectangles(activeArray,
                    zoomData, p.getFocusAreas(), "AF");

            m.set(CONTROL_AF_REGIONS, meteringRectArray);
        }
    }

    private static void mapAwb(CameraMetadataNative m, Camera.Parameters p) {
        // control.awbLock
        {
            boolean lock = p.isAutoWhiteBalanceLockSupported() ?
                    p.getAutoWhiteBalanceLock() : false;
            m.set(CONTROL_AWB_LOCK, lock);
        }

        // control.awbMode
        {
            int awbMode = convertLegacyAwbMode(p.getWhiteBalance());
            m.set(CONTROL_AWB_MODE, awbMode);
        }
    }

    private static MeteringRectangle[] getMeteringRectangles(Rect activeArray, ZoomData zoomData,
            List<Camera.Area> meteringAreaList, String regionName) {
        List<MeteringRectangle> meteringRectList = new ArrayList<>();
        if (meteringAreaList != null) {
            for (Camera.Area area : meteringAreaList) {
                WeightedRectangle rect =
                        ParameterUtils.convertCameraAreaToActiveArrayRectangle(
                                activeArray, zoomData, area);

                meteringRectList.add(rect.toMetering());
            }
        }

        if (DEBUG) {
            Log.v(TAG,
                    "Metering rectangles for " + regionName + ": "
                     + ListUtils.listToString(meteringRectList));
        }

        return meteringRectList.toArray(new MeteringRectangle[0]);
    }

    /** Map results for control.aeMode, flash.mode, flash.state */
    private static void mapAeAndFlashMode(CameraMetadataNative m,
            CameraCharacteristics characteristics, Parameters p) {
        // Default: AE mode on but flash never fires
        int flashMode = FLASH_MODE_OFF;
        // If there is no flash on this camera, the state is always unavailable
        // , otherwise it's only known for TORCH/SINGLE modes
        Integer flashState = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE)
                ? null : FLASH_STATE_UNAVAILABLE;
        int aeMode = CONTROL_AE_MODE_ON;

        String flashModeSetting = p.getFlashMode();

        if (flashModeSetting != null) {
            switch (flashModeSetting) {
                case Parameters.FLASH_MODE_OFF:
                    break; // ok, using default
                case Parameters.FLASH_MODE_AUTO:
                    aeMode = CONTROL_AE_MODE_ON_AUTO_FLASH;
                    break;
                case Parameters.FLASH_MODE_ON:
                    // flashMode = SINGLE + aeMode = ON is indistinguishable from ON_ALWAYS_FLASH
                    flashMode = FLASH_MODE_SINGLE;
                    aeMode = CONTROL_AE_MODE_ON_ALWAYS_FLASH;
                    flashState = FLASH_STATE_FIRED;
                    break;
                case Parameters.FLASH_MODE_RED_EYE:
                    aeMode = CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE;
                    break;
                case Parameters.FLASH_MODE_TORCH:
                    flashMode = FLASH_MODE_TORCH;
                    flashState = FLASH_STATE_FIRED;
                    break;
                default:
                    Log.w(TAG,
                            "mapAeAndFlashMode - Ignoring unknown flash mode " + p.getFlashMode());
            }
        }

        // flash.state
        m.set(FLASH_STATE, flashState);
        // flash.mode
        m.set(FLASH_MODE, flashMode);
        // control.aeMode
        m.set(CONTROL_AE_MODE, aeMode);
    }

    private static int convertLegacyAfMode(String mode) {
        if (mode == null) {
            Log.w(TAG, "convertLegacyAfMode - no AF mode, default to OFF");
            return CONTROL_AF_MODE_OFF;
        }

        switch (mode) {
            case Parameters.FOCUS_MODE_AUTO:
                return CONTROL_AF_MODE_AUTO;
            case Parameters.FOCUS_MODE_CONTINUOUS_PICTURE:
                return CONTROL_AF_MODE_CONTINUOUS_PICTURE;
            case Parameters.FOCUS_MODE_CONTINUOUS_VIDEO:
                return CONTROL_AF_MODE_CONTINUOUS_VIDEO;
            case Parameters.FOCUS_MODE_EDOF:
                return CONTROL_AF_MODE_EDOF;
            case Parameters.FOCUS_MODE_MACRO:
                return CONTROL_AF_MODE_MACRO;
            case Parameters.FOCUS_MODE_FIXED:
                return CONTROL_AF_MODE_OFF;
            case Parameters.FOCUS_MODE_INFINITY:
                return CONTROL_AF_MODE_OFF;
            default:
                Log.w(TAG, "convertLegacyAfMode - unknown mode " + mode + " , ignoring");
                return CONTROL_AF_MODE_OFF;
        }
    }

    private static int convertLegacyAwbMode(String mode) {
        if (mode == null) {
            // OK: camera1 api may not support changing WB modes; assume AUTO
            return CONTROL_AWB_MODE_AUTO;
        }

        switch (mode) {
            case Camera.Parameters.WHITE_BALANCE_AUTO:
                return CONTROL_AWB_MODE_AUTO;
            case Camera.Parameters.WHITE_BALANCE_INCANDESCENT:
                return CONTROL_AWB_MODE_INCANDESCENT;
            case Camera.Parameters.WHITE_BALANCE_FLUORESCENT:
                return CONTROL_AWB_MODE_FLUORESCENT;
            case Camera.Parameters.WHITE_BALANCE_WARM_FLUORESCENT:
                return CONTROL_AWB_MODE_WARM_FLUORESCENT;
            case Camera.Parameters.WHITE_BALANCE_DAYLIGHT:
                return CONTROL_AWB_MODE_DAYLIGHT;
            case Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT:
                return CONTROL_AWB_MODE_CLOUDY_DAYLIGHT;
            case Camera.Parameters.WHITE_BALANCE_TWILIGHT:
                return CONTROL_AWB_MODE_TWILIGHT;
            case Camera.Parameters.WHITE_BALANCE_SHADE:
                return CONTROL_AWB_MODE_SHADE;
            default:
                Log.w(TAG, "convertAwbMode - unrecognized WB mode " + mode);
                return CONTROL_AWB_MODE_AUTO;
        }
    }

    /** Map results for scaler.* */
    private static void mapScaler(CameraMetadataNative m,
            ZoomData zoomData,
            /*out*/Parameters p) {
        /*
         * scaler.cropRegion
         */
        {
            m.set(SCALER_CROP_REGION, zoomData.reportedCrop);
        }

        /*
         * control.zoomRatio
         */
        {
            m.set(CONTROL_ZOOM_RATIO, zoomData.reportedZoomRatio);
        }
    }
}
