/*
 * 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.cts.verifier.camera.its;

import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.Image.Plane;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.util.Size;

import com.android.ex.camera2.blocking.BlockingCameraManager;
import com.android.ex.camera2.blocking.BlockingStateCallback;

import org.json.JSONArray;
import org.json.JSONObject;

import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.Semaphore;
import java.util.List;
import java.util.Set;


public class ItsUtils {
    public static final String TAG = ItsUtils.class.getSimpleName();
    // The tokenizer must be the same as CAMERA_ID_TOKENIZER in device.py
    public static final String CAMERA_ID_TOKENIZER = ".";

    public static ByteBuffer jsonToByteBuffer(JSONObject jsonObj) {
        return ByteBuffer.wrap(jsonObj.toString().getBytes(Charset.defaultCharset()));
    }

    public static MeteringRectangle[] getJsonWeightedRectsFromArray(
            JSONArray a, boolean normalized, int width, int height)
            throws ItsException {
        try {
            // Returns [x0,y0,x1,y1,wgt,  x0,y0,x1,y1,wgt,  x0,y0,x1,y1,wgt,  ...]
            assert(a.length() % 5 == 0);
            MeteringRectangle[] ma = new MeteringRectangle[a.length() / 5];
            for (int i = 0; i < a.length(); i += 5) {
                int x,y,w,h;
                if (normalized) {
                    x = (int)Math.floor(a.getDouble(i+0) * width + 0.5f);
                    y = (int)Math.floor(a.getDouble(i+1) * height + 0.5f);
                    w = (int)Math.floor(a.getDouble(i+2) * width + 0.5f);
                    h = (int)Math.floor(a.getDouble(i+3) * height + 0.5f);
                } else {
                    x = a.getInt(i+0);
                    y = a.getInt(i+1);
                    w = a.getInt(i+2);
                    h = a.getInt(i+3);
                }
                x = Math.max(x, 0);
                y = Math.max(y, 0);
                w = Math.min(w, width-x);
                h = Math.min(h, height-y);
                int wgt = a.getInt(i+4);
                ma[i/5] = new MeteringRectangle(x,y,w,h,wgt);
            }
            return ma;
        } catch (org.json.JSONException e) {
            throw new ItsException("JSON error: ", e);
        }
    }

    public static JSONArray getOutputSpecs(JSONObject jsonObjTop)
            throws ItsException {
        try {
            if (jsonObjTop.has("outputSurfaces")) {
                return jsonObjTop.getJSONArray("outputSurfaces");
            }
            return null;
        } catch (org.json.JSONException e) {
            throw new ItsException("JSON error: ", e);
        }
    }

    public static Size[] getRaw16OutputSizes(CameraCharacteristics ccs)
            throws ItsException {
        return getOutputSizes(ccs, ImageFormat.RAW_SENSOR);
    }

    public static Size[] getRaw10OutputSizes(CameraCharacteristics ccs)
            throws ItsException {
        return getOutputSizes(ccs, ImageFormat.RAW10);
    }

    public static Size[] getRaw12OutputSizes(CameraCharacteristics ccs)
            throws ItsException {
        return getOutputSizes(ccs, ImageFormat.RAW12);
    }

    public static Size[] getJpegOutputSizes(CameraCharacteristics ccs)
            throws ItsException {
        return getOutputSizes(ccs, ImageFormat.JPEG);
    }

    public static Size[] getYuvOutputSizes(CameraCharacteristics ccs)
            throws ItsException {
        return getOutputSizes(ccs, ImageFormat.YUV_420_888);
    }

    public static Size[] getY8OutputSizes(CameraCharacteristics ccs)
            throws ItsException {
        return getOutputSizes(ccs, ImageFormat.Y8);
    }

    public static Size getMaxOutputSize(CameraCharacteristics ccs, int format)
            throws ItsException {
        return getMaxSize(getOutputSizes(ccs, format));
    }

    public static Rect getActiveArrayCropRegion(CameraCharacteristics ccs) {
        return ccs.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
    }

    private static Size[] getOutputSizes(CameraCharacteristics ccs, int format)
            throws ItsException {
        StreamConfigurationMap configMap = ccs.get(
                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
        if (configMap == null) {
            throw new ItsException("Failed to get stream config");
        }
        Size[] normalSizes = configMap.getOutputSizes(format);
        Size[] slowSizes = configMap.getHighResolutionOutputSizes(format);
        Size[] allSizes = null;
        if (normalSizes != null && slowSizes != null) {
            allSizes = new Size[normalSizes.length + slowSizes.length];
            System.arraycopy(normalSizes, 0, allSizes, 0,
                    normalSizes.length);
            System.arraycopy(slowSizes, 0, allSizes, normalSizes.length,
                    slowSizes.length);
        } else if (normalSizes != null) {
            allSizes = normalSizes;
        } else if (slowSizes != null) {
            allSizes = slowSizes;
        }
        return allSizes;
    }

    public static Size getMaxSize(Size[] sizes) {
        if (sizes == null || sizes.length == 0) {
            throw new IllegalArgumentException("sizes was empty");
        }

        Size maxSize = sizes[0];
        int maxArea = maxSize.getWidth() * maxSize.getHeight();
        for (int i = 1; i < sizes.length; i++) {
            int area = sizes[i].getWidth() * sizes[i].getHeight();
            if (area > maxArea ||
                    (area == maxArea && sizes[i].getWidth() > maxSize.getWidth())) {
                maxSize = sizes[i];
                maxArea = area;
            }
        }

        return maxSize;
    }

    public static byte[] getDataFromImage(Image image, Semaphore quota)
            throws ItsException {
        int format = image.getFormat();
        int width = image.getWidth();
        int height = image.getHeight();
        byte[] data = null;

        // Read image data
        Plane[] planes = image.getPlanes();

        // Check image validity
        if (!checkAndroidImageFormat(image)) {
            throw new ItsException(
                    "Invalid image format passed to getDataFromImage: " + image.getFormat());
        }

        if (format == ImageFormat.JPEG) {
            // JPEG doesn't have pixelstride and rowstride, treat it as 1D buffer.
            ByteBuffer buffer = planes[0].getBuffer();
            if (quota != null) {
                try {
                    Logt.i(TAG, "Start waiting for quota Semaphore");
                    quota.acquire(buffer.capacity());
                    Logt.i(TAG, "Acquired quota Semaphore. Start reading image");
                } catch (java.lang.InterruptedException e) {
                    Logt.e(TAG, "getDataFromImage error acquiring memory quota. Interrupted", e);
                }
            }
            data = new byte[buffer.capacity()];
            buffer.get(data);
            Logt.i(TAG, "Done reading jpeg image");
            return data;
        } else if (format == ImageFormat.YUV_420_888 || format == ImageFormat.RAW_SENSOR
                || format == ImageFormat.RAW10 || format == ImageFormat.RAW12
                || format == ImageFormat.Y8) {
            int offset = 0;
            int dataSize = width * height * ImageFormat.getBitsPerPixel(format) / 8;
            if (quota != null) {
                try {
                    Logt.i(TAG, "Start waiting for quota Semaphore");
                    quota.acquire(dataSize);
                    Logt.i(TAG, "Acquired quota Semaphore. Start reading image");
                } catch (java.lang.InterruptedException e) {
                    Logt.e(TAG, "getDataFromImage error acquiring memory quota. Interrupted", e);
                }
            }
            data = new byte[dataSize];
            int maxRowSize = planes[0].getRowStride();
            for (int i = 0; i < planes.length; i++) {
                if (maxRowSize < planes[i].getRowStride()) {
                    maxRowSize = planes[i].getRowStride();
                }
            }
            byte[] rowData = new byte[maxRowSize];
            for (int i = 0; i < planes.length; i++) {
                ByteBuffer buffer = planes[i].getBuffer();
                int rowStride = planes[i].getRowStride();
                int pixelStride = planes[i].getPixelStride();
                int bytesPerPixel = ImageFormat.getBitsPerPixel(format) / 8;
                Logt.i(TAG, String.format(
                        "Reading image: fmt %d, plane %d, w %d, h %d," +
                        "rowStride %d, pixStride %d, bytesPerPixel %d",
                        format, i, width, height, rowStride, pixelStride, bytesPerPixel));
                // For multi-planar yuv images, assuming yuv420 with 2x2 chroma subsampling.
                int w = (i == 0) ? width : width / 2;
                int h = (i == 0) ? height : height / 2;
                for (int row = 0; row < h; row++) {
                    if (pixelStride == bytesPerPixel) {
                        // Special case: optimized read of the entire row
                        int length = w * bytesPerPixel;
                        buffer.get(data, offset, length);
                        // Advance buffer the remainder of the row stride
                        if (row < h - 1) {
                            buffer.position(buffer.position() + rowStride - length);
                        }
                        offset += length;
                    } else {
                        // Generic case: should work for any pixelStride but slower.
                        // Use intermediate buffer to avoid read byte-by-byte from
                        // DirectByteBuffer, which is very bad for performance.
                        // Also need avoid access out of bound by only reading the available
                        // bytes in the bytebuffer.
                        int readSize = rowStride;
                        if (buffer.remaining() < readSize) {
                            readSize = buffer.remaining();
                        }
                        buffer.get(rowData, 0, readSize);
                        if (pixelStride >= 1) {
                            for (int col = 0; col < w; col++) {
                                data[offset++] = rowData[col * pixelStride];
                            }
                        } else {
                            // PixelStride of 0 can mean pixel isn't a multiple of 8 bits, for
                            // example with RAW10. Just copy the buffer, dropping any padding at
                            // the end of the row.
                            int length = (w * ImageFormat.getBitsPerPixel(format)) / 8;
                            System.arraycopy(rowData,0,data,offset,length);
                            offset += length;
                        }
                    }
                }
            }
            Logt.i(TAG, String.format("Done reading image, format %d", format));
            return data;
        } else {
            throw new ItsException("Unsupported image format: " + format);
        }
    }

    private static boolean checkAndroidImageFormat(Image image) {
        int format = image.getFormat();
        Plane[] planes = image.getPlanes();
        switch (format) {
            case ImageFormat.YUV_420_888:
            case ImageFormat.NV21:
            case ImageFormat.YV12:
                return 3 == planes.length;
            case ImageFormat.RAW_SENSOR:
            case ImageFormat.RAW10:
            case ImageFormat.RAW12:
            case ImageFormat.JPEG:
            case ImageFormat.Y8:
                return 1 == planes.length;
            default:
                return false;
        }
    }

    public static class ItsCameraIdList {
        // Short form camera Ids (including both CameraIdList and hidden physical cameras
        public List<String> mCameraIds;
        // Camera Id combos (ids from CameraIdList, and hidden physical camera Ids
        // in the form of [logical camera id]:[hidden physical camera id]
        public List<String> mCameraIdCombos;
        // Primary rear and front camera Ids (as defined in MPC)
        public String mPrimaryRearCameraId;
        public String mPrimaryFrontCameraId;
    }

    public static ItsCameraIdList getItsCompatibleCameraIds(CameraManager manager)
            throws ItsException {
        if (manager == null) {
            throw new IllegalArgumentException("CameraManager is null");
        }

        ItsCameraIdList outList = new ItsCameraIdList();
        outList.mCameraIds = new ArrayList<String>();
        outList.mCameraIdCombos = new ArrayList<String>();
        try {
            String[] cameraIds = manager.getCameraIdList();
            for (String id : cameraIds) {
                CameraCharacteristics characteristics = manager.getCameraCharacteristics(id);
                int[] actualCapabilities = characteristics.get(
                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
                boolean haveBC = false;
                boolean isMultiCamera = false;
                final int BACKWARD_COMPAT =
                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE;
                final int LOGICAL_MULTI_CAMERA =
                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA;

                final Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
                if (facing != null) {
                    if (facing == CameraMetadata.LENS_FACING_BACK
                            && outList.mPrimaryRearCameraId == null) {
                        outList.mPrimaryRearCameraId = id;
                    } else if (facing == CameraMetadata.LENS_FACING_FRONT
                            && outList.mPrimaryFrontCameraId == null) {
                        outList.mPrimaryFrontCameraId = id;
                    }
                }

                for (int capability : actualCapabilities) {
                    if (capability == BACKWARD_COMPAT) {
                        haveBC = true;
                    }
                    if (capability == LOGICAL_MULTI_CAMERA) {
                        isMultiCamera = true;
                    }
                }

                // Skip devices that does not support BACKWARD_COMPATIBLE capability
                if (!haveBC) continue;

                int hwLevel = characteristics.get(
                        CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
                if (hwLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY ||
                        hwLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL) {
                    // Skip LEGACY and EXTERNAL devices
                    continue;
                }
                outList.mCameraIds.add(id);
                outList.mCameraIdCombos.add(id);

                // Only add hidden physical cameras for multi-camera.
                if (!isMultiCamera) continue;

                float defaultFocalLength = getLogicalCameraDefaultFocalLength(manager, id);
                Set<String> physicalIds = characteristics.getPhysicalCameraIds();
                for (String physicalId : physicalIds) {
                    if (Arrays.asList(cameraIds).contains(physicalId)) continue;

                    CameraCharacteristics physicalChar =
                            manager.getCameraCharacteristics(physicalId);
                    hwLevel = physicalChar.get(
                            CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
                    if (hwLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY ||
                            hwLevel ==
                            CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL) {
                        // Skip LEGACY and EXTERNAL devices
                        continue;
                    }

                    int[] physicalActualCapabilities = physicalChar.get(
                            CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
                    boolean physicalHaveBC = false;
                    for (int capability : physicalActualCapabilities) {
                        if (capability == BACKWARD_COMPAT) {
                            physicalHaveBC = true;
                            break;
                        }
                    }
                    if (!physicalHaveBC) {
                        continue;
                    }
                    // To reduce duplicate tests, only additionally test hidden physical cameras
                    // with different focal length compared to the default focal length of the
                    // logical camera.
                    float[] physicalFocalLengths = physicalChar.get(
                            CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS);
                    if (defaultFocalLength != physicalFocalLengths[0]) {
                        outList.mCameraIds.add(physicalId);
                        outList.mCameraIdCombos.add(id + CAMERA_ID_TOKENIZER + physicalId);
                    }
                }

            }
        } catch (CameraAccessException e) {
            Logt.e(TAG,
                    "Received error from camera service while checking device capabilities: " + e);
            throw new ItsException("Failed to get device ID list", e);
        }
        return outList;
    }

    public static float getLogicalCameraDefaultFocalLength(CameraManager manager,
            String cameraId) throws ItsException {
        BlockingCameraManager blockingManager = new BlockingCameraManager(manager);
        BlockingStateCallback listener = new BlockingStateCallback();
        HandlerThread cameraThread = new HandlerThread("ItsUtilThread");
        cameraThread.start();
        Handler cameraHandler = new Handler(cameraThread.getLooper());
        CameraDevice camera = null;
        float defaultFocalLength = 0.0f;

        try {
            camera = blockingManager.openCamera(cameraId, listener, cameraHandler);
            CaptureRequest.Builder previewBuilder =
                    camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            defaultFocalLength = previewBuilder.get(CaptureRequest.LENS_FOCAL_LENGTH);
        } catch (Exception e) {
            throw new ItsException("Failed to query default focal length for logical camera", e);
        } finally {
            if (camera != null) {
                camera.close();
            }
            if (cameraThread != null) {
                cameraThread.quitSafely();
            }
        }
        return defaultFocalLength;
    }
}
