/*
 * Copyright (C) 2017, The LineageOS 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.
 */

#define LOG_NDEBUG 1

#define LOG_TAG "Camera3Wrapper"
#include <cutils/log.h>

#include "CameraWrapper.h"
#include "Camera3Wrapper.h"

typedef struct wrapper_camera3_device {
    camera3_device_t base;
    int id;
    camera3_device_t *vendor;
} wrapper_camera3_device_t;

#define VENDOR_CALL(device, func, ...) ({ \
    wrapper_camera3_device_t *__wrapper_dev = (wrapper_camera3_device_t*) device; \
    __wrapper_dev->vendor->ops->func(__wrapper_dev->vendor, ##__VA_ARGS__); \
})

#define CAMERA_ID(device) (((wrapper_camera3_device_t *)(device))->id)

static camera_module_t *gVendorModule = 0;

static int check_vendor_module()
{
    int rv = 0;
    ALOGV("%s", __FUNCTION__);

    if(gVendorModule)
        return 0;

    rv = hw_get_module_by_class("camera", "vendor", (const hw_module_t **)&gVendorModule);
    if (rv)
        ALOGE("failed to open vendor camera module");
    return rv;
}

/*******************************************************************
 * implementation of camera_device_ops functions
 *******************************************************************/

static int camera3_initialize(const camera3_device_t *device, const camera3_callback_ops_t *callback_ops)
{
    ALOGV("%s->%zu->%zu", __FUNCTION__, (uintptr_t)device,
        (uintptr_t)(((wrapper_camera3_device_t*)device)->vendor));

    if (!device)
        return -1;

    return VENDOR_CALL(device, initialize, callback_ops);
}

static int camera3_configure_streams(const camera3_device *device, camera3_stream_configuration_t *stream_list)
{
    ALOGV("%s->%zu->%zu", __FUNCTION__, (uintptr_t)device,
        (uintptr_t)(((wrapper_camera3_device_t*)device)->vendor));

    if (!device)
        return -1;

    return VENDOR_CALL(device, configure_streams, stream_list);
}

__unused static int camera3_register_stream_buffers(const camera3_device *device, const camera3_stream_buffer_set_t *buffer_set)
{
    ALOGV("%s->%zu->%zu", __FUNCTION__, (uintptr_t)device,
        (uintptr_t)(((wrapper_camera3_device_t*)device)->vendor));

    if (!device)
        return -1;

    return VENDOR_CALL(device, register_stream_buffers, buffer_set);
}

static const camera_metadata_t *camera3_construct_default_request_settings(const camera3_device_t *device, int type)
{
    ALOGV("%s->%zu->%zu", __FUNCTION__, (uintptr_t)device,
        (uintptr_t)(((wrapper_camera3_device_t*)device)->vendor));

    if (!device)
        return NULL;

    return VENDOR_CALL(device, construct_default_request_settings, type);
}

static int camera3_process_capture_request(const camera3_device_t *device, camera3_capture_request_t *request)
{
    ALOGV("%s->%zu->%zu", __FUNCTION__, (uintptr_t)device,
        (uintptr_t)(((wrapper_camera3_device_t*)device)->vendor));

    if (!device)
        return -1;

    return VENDOR_CALL(device, process_capture_request, request);
}

static void camera3_get_metadata_vendor_tag_ops(const camera3_device *device, vendor_tag_query_ops_t* ops)
{
    ALOGV("%s->%zu->%zu", __FUNCTION__, (uintptr_t)device,
        (uintptr_t)(((wrapper_camera3_device_t*)device)->vendor));

    if (!device)
        return;

    VENDOR_CALL(device, get_metadata_vendor_tag_ops, ops);
}

static void camera3_dump(const camera3_device_t *device, int fd)
{
    ALOGV("%s->%zu->%zu", __FUNCTION__, (uintptr_t)device,
        (uintptr_t)(((wrapper_camera3_device_t*)device)->vendor));

    if (!device)
        return;

    VENDOR_CALL(device, dump, fd);
}

static int camera3_flush(const camera3_device_t* device)
{
    ALOGV("%s->%zu->%zu", __FUNCTION__, (uintptr_t)device,
        (uintptr_t)(((wrapper_camera3_device_t*)device)->vendor));

    if (!device)
        return -1;

    return VENDOR_CALL(device, flush);
}

static int camera3_device_close(hw_device_t *device)
{
    int ret = 0;
    wrapper_camera3_device_t *wrapper_dev = NULL;

    ALOGV("%s", __FUNCTION__);

    android::Mutex::Autolock lock(gCameraWrapperLock);

    if (!device) {
        ret = -EINVAL;
        goto done;
    }

    wrapper_dev = (wrapper_camera3_device_t*) device;

    wrapper_dev->vendor->common.close((hw_device_t*)wrapper_dev->vendor);
    if (wrapper_dev->base.ops)
        free(wrapper_dev->base.ops);
    free(wrapper_dev);
done:
    return ret;
}

/*******************************************************************
 * implementation of camera_module functions
 *******************************************************************/

/* open device handle to one of the cameras
 *
 * assume camera service will keep singleton of each camera
 * so this function will always only be called once per camera instance
 */

int camera3_device_open(const hw_module_t *module, const char *name,
        hw_device_t **device)
{
    int rv = 0;
    int num_cameras = 0;
    int cameraid;
    wrapper_camera3_device_t *camera3_device = NULL;
    camera3_device_ops_t *camera3_ops = NULL;

    android::Mutex::Autolock lock(gCameraWrapperLock);

    ALOGV("%s", __FUNCTION__);

    if (name != NULL) {
        if (check_vendor_module())
            return -EINVAL;

        cameraid = atoi(name);
        num_cameras = gVendorModule->get_number_of_cameras();

        if (cameraid > num_cameras) {
            ALOGE("camera service provided cameraid out of bounds, "
                    "cameraid = %d, num supported = %d",
                    cameraid, num_cameras);
            rv = -EINVAL;
            goto fail;
        }

        camera3_device = (wrapper_camera3_device_t*)malloc(sizeof(*camera3_device));
        if (!camera3_device) {
            ALOGE("camera3_device allocation fail");
            rv = -ENOMEM;
            goto fail;
        }
        memset(camera3_device, 0, sizeof(*camera3_device));
        camera3_device->id = cameraid;

        rv = gVendorModule->common.methods->open((const hw_module_t*)gVendorModule, name, (hw_device_t**)&(camera3_device->vendor));
        if (rv)
        {
            ALOGE("vendor camera open fail");
            goto fail;
        }
        ALOGV("%s: got vendor camera device 0x%zu", __FUNCTION__, (uintptr_t)(camera3_device->vendor));

        camera3_ops = (camera3_device_ops_t*)malloc(sizeof(*camera3_ops));
        if (!camera3_ops) {
            ALOGE("camera3_ops allocation fail");
            rv = -ENOMEM;
            goto fail;
        }

        memset(camera3_ops, 0, sizeof(*camera3_ops));

        camera3_device->base.common.tag = HARDWARE_DEVICE_TAG;
        camera3_device->base.common.version = CAMERA_DEVICE_API_VERSION_3_4;
        camera3_device->base.common.module = (hw_module_t *)(module);
        camera3_device->base.common.close = camera3_device_close;
        camera3_device->base.ops = camera3_ops;

        camera3_ops->initialize = camera3_initialize;
        camera3_ops->configure_streams = camera3_configure_streams;
        camera3_ops->register_stream_buffers = NULL;
        camera3_ops->construct_default_request_settings = camera3_construct_default_request_settings;
        camera3_ops->process_capture_request = camera3_process_capture_request;
        camera3_ops->get_metadata_vendor_tag_ops = camera3_get_metadata_vendor_tag_ops;
        camera3_ops->dump = camera3_dump;
        camera3_ops->flush = camera3_flush;

        *device = &camera3_device->base.common;
    }

    return rv;

fail:
    if (camera3_device) {
        free(camera3_device);
        camera3_device = NULL;
    }
    if (camera3_ops) {
        free(camera3_ops);
        camera3_ops = NULL;
    }
    *device = NULL;
    return rv;
}
