/*
 * Copyright (C) 2013-2020 Intel Corporation
 *
 * 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_TAG "Camera3HALModule"

#include <dlfcn.h>
#include <stdlib.h>
#include <mutex>

#include <cros-camera/cros_camera_hal.h>
#include <hardware/camera3.h>

#include "LogHelper.h"
#include "PlatformData.h"
#include "PerformanceTraces.h"

#include "Camera3HAL.h"

using namespace cros;
using namespace cros::intel;

/**
 * \macro VISIBILITY_PUBLIC
 *
 * Controls the visibility of symbols in the shared library.
 * In production builds all symbols in the shared library are hidden
 * except the ones using this linker attribute.
 */
#define VISIBILITY_PUBLIC __attribute__ ((visibility ("default")))

static int hal_dev_close(hw_device_t* device);

/**********************************************************************
 * Camera Module API (C API)
 **********************************************************************/

static bool sInstances[MAX_CAMERAS] = {false, false};
static int sInstanceCount = 0;

/**
 * Global mutex used to protect sInstanceCount and sInstances
 */
static std::mutex sCameraHalMutex;

CameraMojoChannelManager* cros::intel::g_mojo_manager = nullptr;

int openCameraHardware(int id, const hw_module_t* module, hw_device_t** device)
{
    HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);

    if (sInstances[id])
        return 0;

    Camera3HAL* halDev = new Camera3HAL(id, module);

    if (halDev->init() != NO_ERROR) {
        LOGE("HAL initialization fail!");
        delete halDev;
        return -EINVAL;
    }
    camera3_device_t *cam3Device = halDev->getDeviceStruct();

    cam3Device->common.close = hal_dev_close;
    *device = &cam3Device->common;

    sInstanceCount++;
    sInstances[id] = true;

    return 0;
}

static int hal_get_number_of_cameras(void)
{
    LogHelper::setDebugLevel();
    PerformanceTraces::reset();
    PerformanceTraces::HalAtrace::reset();

    HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);

    PERFORMANCE_HAL_ATRACE();

    return PlatformData::numberOfCameras();
}

static int hal_get_camera_info(int cameraId, struct camera_info *cameraInfo)
{
    PERFORMANCE_HAL_ATRACE();
    HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);

    if (cameraId < 0 || !cameraInfo ||
          cameraId >= hal_get_number_of_cameras())
        return -EINVAL;

    PlatformData::getCameraInfo(cameraId, cameraInfo);

    return 0;
}

static int hal_set_callbacks(const camera_module_callbacks_t *callbacks)
{
    HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);

    UNUSED(callbacks);
    return 0;
}

static int hal_dev_open(const hw_module_t* module, const char* name,
                        hw_device_t** device)
{
    int status = -EINVAL;
    int camera_id;

    HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
    LogHelper::setDebugLevel();
    PerformanceTraces::reset();
    PerformanceTraces::HalAtrace::reset();

    PERFORMANCE_HAL_ATRACE();

    if (!name || !module || !device) {
        LOGE("Camera name is nullptr");
        return status;
    }

    LOG1("%s, camera id: %s", __FUNCTION__, name);
    camera_id = atoi(name);

    if (PlatformData::getIntel3AClient()
        && !PlatformData::getIntel3AClient()->isIPCFine()) {
        PlatformData::deinit();
        LOGW("@%s, remote 3A IPC fails", __FUNCTION__);
    }

    if (!PlatformData::isInitialized()) {
        PlatformData::init(); // try to init the PlatformData again.
        if (!PlatformData::isInitialized()) {
            LOGE("%s: open Camera id %d fails due to PlatformData init fails",
                __func__, camera_id);
            return -ENODEV;
        }
    }

    if (camera_id < 0 || camera_id >= hal_get_number_of_cameras()) {
        LOGE("%s: Camera id %d is out of bounds, num. of cameras (%d)",
             __func__, camera_id, hal_get_number_of_cameras());
        return -ENODEV;
    }

    std::lock_guard<std::mutex> l(sCameraHalMutex);

    if ((!PlatformData::supportDualVideo()) &&
         sInstanceCount > 0 && !sInstances[camera_id]) {
        LOGE("Don't support front/primary open at the same time");
        return -EUSERS;
    }

    PlatformData::readNvmDataFromDevice(camera_id);

    return openCameraHardware(camera_id, module, device);
}

static int hal_dev_close(hw_device_t* device)
{
    PERFORMANCE_HAL_ATRACE();
    HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);

    if (!device || sInstanceCount == 0) {
        LOGW("hal close, instance count %d", sInstanceCount);
        return -EINVAL;
    }

    camera3_device_t *camera3_dev = (struct camera3_device *)device;
    Camera3HAL* camera_priv = (Camera3HAL*)(camera3_dev->priv);

    if (camera_priv != nullptr) {
        std::lock_guard<std::mutex> l(sCameraHalMutex);
        camera_priv->deinit();
        int id = camera_priv->getCameraId();
        delete camera_priv;
        sInstanceCount--;
        sInstances[id] = false;
    }

    LOG1("%s, instance count %d", __FUNCTION__, sInstanceCount);

    return 0;
}

static int hal_open_legacy(
    const struct hw_module_t* module,
    const char* id,
    uint32_t halVersion,
    struct hw_device_t** device)
{
    HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);

    UNUSED(module);
    UNUSED(id);
    UNUSED(halVersion);
    UNUSED(device);
    return -ENOSYS;
}

static int hal_set_torch_mode(const char* camera_id, bool enabled)
{
    HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);

    UNUSED(camera_id);
    UNUSED(enabled);
    return -ENOSYS;
}

static int hal_init()
{
    HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);

    if (PlatformData::numberOfCameras() == 0) {
        LOGE("Init failed bacause no camera device was found.");
        return -ENODEV;
    }
    return 0;
}

static void set_up(CameraMojoChannelManager* mojo_manager)
{
    cros::intel::g_mojo_manager = mojo_manager;

    LogHelper::setDebugLevel();
    PerformanceTraces::reset();
    PlatformData::init();
    int ret = PlatformData::numberOfCameras();
    if (ret == 0) {
        LOGE("No camera device was found!");
        return;
    }
}

static void tear_down()
{
    PlatformData::deinit();

    cros::intel::g_mojo_manager = nullptr;
}

static struct hw_module_methods_t hal_module_methods = {
    NAMED_FIELD_INITIALIZER(open) hal_dev_open
};

camera_module_t VISIBILITY_PUBLIC HAL_MODULE_INFO_SYM = {
    NAMED_FIELD_INITIALIZER(common) {
        NAMED_FIELD_INITIALIZER(tag) HARDWARE_MODULE_TAG,
        NAMED_FIELD_INITIALIZER(module_api_version) CAMERA_MODULE_API_VERSION_2_4,
        NAMED_FIELD_INITIALIZER(hal_api_version) 0,
        NAMED_FIELD_INITIALIZER(id) CAMERA_HARDWARE_MODULE_ID,
        NAMED_FIELD_INITIALIZER(name) "Intel Camera3HAL Module",
        NAMED_FIELD_INITIALIZER(author) "Intel",
        NAMED_FIELD_INITIALIZER(methods) &hal_module_methods,
        NAMED_FIELD_INITIALIZER(dso) nullptr,
        NAMED_FIELD_INITIALIZER(reserved) {0},
    },
    NAMED_FIELD_INITIALIZER(get_number_of_cameras) hal_get_number_of_cameras,
    NAMED_FIELD_INITIALIZER(get_camera_info) hal_get_camera_info,
    NAMED_FIELD_INITIALIZER(set_callbacks) hal_set_callbacks,
    NAMED_FIELD_INITIALIZER(open_legacy) hal_open_legacy,
    NAMED_FIELD_INITIALIZER(set_torch_mode) hal_set_torch_mode,
    NAMED_FIELD_INITIALIZER(init) hal_init,
    NAMED_FIELD_INITIALIZER(reserved) {0}
};

cros::cros_camera_hal_t VISIBILITY_PUBLIC CROS_CAMERA_HAL_INFO_SYM = {
    NAMED_FIELD_INITIALIZER(set_up) set_up,
    NAMED_FIELD_INITIALIZER(tear_down) tear_down
};
