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

CameraMojoChannelManagerToken* cros::intel::g_mojo_manager_token = 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(CameraMojoChannelManagerToken* token)
{
    cros::intel::g_mojo_manager_token = token;

    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_token = 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
};
