/*
 *
 *    Copyright (c) 2016 Nest Labs, Inc.
 *    All rights reserved.
 *
 *    This document is the property of Nest. It is considered
 *    confidential and proprietary information.
 *
 *    This document may not be reproduced or transmitted in any form,
 *    in whole or in part, without the express written permission of
 *    Nest.
 *
 */

#define LOG_NDEBUG 0
#define LOG_TAG "NestOverlay"

#include <Overlay.h>

#include <system/window.h>
#include <overlay/QIPCamOverlay.h>

namespace
{
constexpr char WATERMARK_1080P_PATH[] = "/system/etc/watermark-1080p.rgba";
constexpr char WATERMARK_720P_PATH[]  = "/system/etc/watermark-720p.rgba";
constexpr char WATERMARK_360P_PATH[]  = "/system/etc/watermark-360p.rgba";
}

namespace android {

namespace nest {

Overlay::Overlay(int width, int height)
    : mWidth(width),
      mHeight(height),
      // TODO(guangshuo): to support other formats if needed
      mFormat(ipcamOverlay::BufferFormat::FORMAT_YUV_NV21),
      mOverlay(new ipcamOverlay::QIPCamOverlay()),
      mWatermarkOverlayId(-1) {
    mOverlay->init(mFormat);
    if (configureWatermark() != OK) {
        ALOGE("Failed to configure watermark");
        return;
    }
}

Overlay::~Overlay() {
    delete mOverlay;
}

status_t Overlay::enableWatermark() {
    status_t ret = mOverlay->enableOverlayItem(mWatermarkOverlayId);
    if (ret != OK) {
        ALOGE("Failed to enable watermark");
    } else {
        ALOGI("enableWatermark, id=%d", mWatermarkOverlayId);
    }
    return ret;
}

status_t Overlay::disableWatermark() {
    status_t ret = mOverlay->disableOverlayItem(mWatermarkOverlayId);
    if (ret != OK) {
        ALOGE("Failed to disable watermark");
    } else {
        ALOGI("disableWatermark, id=%d", mWatermarkOverlayId);
    }
    return ret;
}

void Overlay::applyOverlay(ANativeWindowBuffer* buf) {
    ALOGV("applyOverlay E");
    ipcamOverlay::TargetBuf targetBuf;
    memset(&targetBuf, 0x0, sizeof(targetBuf));

    buffer_handle_t nativeHandle = buf->handle;
    targetBuf.format = mFormat;
    targetBuf.ionFd = nativeHandle->data[0];
    targetBuf.frameLen = nativeHandle->data[2];
    targetBuf.width = mWidth;
    targetBuf.height = mHeight;

    mOverlay->applyOverlay(targetBuf);
    ALOGV("applyOverlay X, ionFd=%d, len=%d, w=%d, h=%d",
        targetBuf.ionFd, targetBuf.frameLen,
        targetBuf.width, targetBuf.height);
}

status_t Overlay::configureWatermark() {
    const char *watermarkPath  = nullptr;
    int watermarkWidth = 0, watermarkHeight = 0;
    switch (mHeight) {
        case 1080:
            if (mWidth != 1920)
            {
                ALOGE("Unsupported resolution, expecting 1920x1080");
                return BAD_VALUE;
            }
            watermarkPath   = WATERMARK_1080P_PATH;
            watermarkWidth  = 192;
            watermarkHeight = 96;
            break;
        case 720:
            if (mWidth != 1280)
            {
                ALOGE("Unsupported resolution, expecting 1280x720");
                return BAD_VALUE;
            }
            watermarkPath   = WATERMARK_720P_PATH;
            watermarkWidth  = 128;
            watermarkHeight = 64;
            break;
        case 360:
            if (mWidth != 640)
            {
                ALOGE("Unsupported resolution, expecting 640x360");
                return BAD_VALUE;
            }
            watermarkPath   = WATERMARK_360P_PATH;
            watermarkWidth  = 64;
            watermarkHeight = 32;
            break;
        default:
            ALOGE("Unsupported resolution: %dx%d", mWidth, mHeight);
            return BAD_VALUE;
    }

    ipcamOverlay::OverlayItemParam params;
    memset(&params, 0x0, sizeof(params));
    params.type     = ipcamOverlay::OverlayType::OVERLAYTYPE_STATICIMAGE;
    params.location = ipcamOverlay::OverlayLocationType::OVERLAYLOCATIONTYPE_TOPRIGHT;
    strlcpy(params.imageInfo.imageLocation,
            watermarkPath,
            sizeof(params.imageInfo.imageLocation));
    params.imageInfo.width  = watermarkWidth;
    params.imageInfo.height = watermarkHeight;
    status_t ret = mOverlay->createOverlayItem(params, &mWatermarkOverlayId);
    ALOGD("configureWatermark, w=%d, h=%d, watermark_w=%d, watermark_h=%d, id=%d",
        mWidth, mHeight, watermarkWidth, watermarkHeight, mWatermarkOverlayId);
    return ret;
}

} // namespace nest

} // namespace android
