/*
 *  Copyright (c) 2013-14, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *     * Neither the name of The Linux Foundation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR CLIENTS; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <hwc_qclient.h>
#include <IQService.h>
#include <hwc_utils.h>
#include <hwc_vpuclient.h>

#define QCLIENT_DEBUG 0

using namespace android;
using namespace qService;
using namespace qhwc;

namespace qClient {

// ----------------------------------------------------------------------------
QClient::QClient(hwc_context_t *ctx) : mHwcContext(ctx),
        mMPDeathNotifier(new MPDeathNotifier(ctx))
{
    ALOGD_IF(QCLIENT_DEBUG, "QClient Constructor invoked");
}

QClient::~QClient()
{
    ALOGD_IF(QCLIENT_DEBUG,"QClient Destructor invoked");
}

static void securing(hwc_context_t *ctx, uint32_t startEnd) {
    Locker::Autolock _sl(ctx->mDrawLock);
    //The only way to make this class in this process subscribe to media
    //player's death.
    IMediaDeathNotifier::getMediaPlayerService();

    ctx->mSecuring = startEnd;
    //We're done securing
    if(startEnd == IQService::END)
        ctx->mSecureMode = true;
    if(ctx->proc)
        ctx->proc->invalidate(ctx->proc);
}

static void unsecuring(hwc_context_t *ctx, uint32_t startEnd) {
    Locker::Autolock _sl(ctx->mDrawLock);
    ctx->mSecuring = startEnd;
    //We're done unsecuring
    if(startEnd == IQService::END)
        ctx->mSecureMode = false;
    if(ctx->proc)
        ctx->proc->invalidate(ctx->proc);
}

void QClient::MPDeathNotifier::died() {
    Locker::Autolock _sl(mHwcContext->mDrawLock);
    ALOGD_IF(QCLIENT_DEBUG, "Media Player died");
    mHwcContext->mSecuring = false;
    mHwcContext->mSecureMode = false;
    if(mHwcContext->proc)
        mHwcContext->proc->invalidate(mHwcContext->proc);
}

static android::status_t screenRefresh(hwc_context_t *ctx) {
    status_t result = NO_INIT;
    if(ctx->proc) {
        ctx->proc->invalidate(ctx->proc);
        result = NO_ERROR;
    }
    return result;
}

static android::status_t vpuCommand(hwc_context_t *ctx,
        uint32_t command,
        const Parcel* inParcel,
        Parcel* outParcel) {
    status_t result = NO_INIT;
#ifdef VPU_TARGET
    result = ctx->mVPUClient->processCommand(command, inParcel, outParcel);
#endif
    return result;
}

static void setExtOrientation(hwc_context_t *ctx, uint32_t orientation) {
    ctx->mExtOrientation = orientation;
}

static void isExternalConnected(hwc_context_t* ctx, Parcel* outParcel) {
    int connected;
    connected = ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected ? 1 : 0;
    outParcel->writeInt32(connected);
}

static void getDisplayAttributes(hwc_context_t* ctx, const Parcel* inParcel,
        Parcel* outParcel) {
    int dpy = inParcel->readInt32();
    outParcel->writeInt32(ctx->dpyAttr[dpy].vsync_period);
    outParcel->writeInt32(ctx->dpyAttr[dpy].xres);
    outParcel->writeInt32(ctx->dpyAttr[dpy].yres);
    outParcel->writeFloat(ctx->dpyAttr[dpy].xdpi);
    outParcel->writeFloat(ctx->dpyAttr[dpy].ydpi);
    //XXX: Need to check what to return for HDMI
    outParcel->writeInt32(ctx->mMDP.panel);
}
static void setHSIC(hwc_context_t* ctx, const Parcel* inParcel) {
    int dpy = inParcel->readInt32();
    HSICData_t hsic_data;
    hsic_data.hue = inParcel->readInt32();
    hsic_data.saturation = inParcel->readFloat();
    hsic_data.intensity = inParcel->readInt32();
    hsic_data.contrast = inParcel->readFloat();
    //XXX: Actually set the HSIC data through ABL lib
}


static void setBufferMirrorMode(hwc_context_t *ctx, uint32_t enable) {
    ctx->mBufferMirrorMode = enable;
}

static status_t getDisplayVisibleRegion(hwc_context_t* ctx, int dpy,
                                Parcel* outParcel) {
    // Get the info only if the dpy is valid
    if(dpy >= HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
        Locker::Autolock _sl(ctx->mDrawLock);
        if(dpy && (ctx->mExtOrientation || ctx->mBufferMirrorMode)) {
            // Return the destRect on external, if external orienation
            // is enabled
            outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.left);
            outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.top);
            outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.right);
            outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.bottom);
        } else {
            outParcel->writeInt32(ctx->mViewFrame[dpy].left);
            outParcel->writeInt32(ctx->mViewFrame[dpy].top);
            outParcel->writeInt32(ctx->mViewFrame[dpy].right);
            outParcel->writeInt32(ctx->mViewFrame[dpy].bottom);
        }
        return NO_ERROR;
    } else {
        ALOGE("In %s: invalid dpy index %d", __FUNCTION__, dpy);
        return BAD_VALUE;
    }
}

static void pauseWFD(hwc_context_t *ctx, uint32_t pause) {
    int dpy = HWC_DISPLAY_VIRTUAL;
    if(pause) {
        //WFD Pause
        handle_pause(ctx, dpy);
    } else {
        //WFD Resume
        handle_resume(ctx, dpy);
    }
}

status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
        Parcel* outParcel) {
    status_t ret = NO_ERROR;

    if (command > IQService::VPU_COMMAND_LIST_START &&
        command < IQService::VPU_COMMAND_LIST_END) {
        return vpuCommand(mHwcContext, command, inParcel, outParcel);
    }

    switch(command) {
        case IQService::SECURING:
            securing(mHwcContext, inParcel->readInt32());
            break;
        case IQService::UNSECURING:
            unsecuring(mHwcContext, inParcel->readInt32());
            break;
        case IQService::SCREEN_REFRESH:
            return screenRefresh(mHwcContext);
            break;
        case IQService::EXTERNAL_ORIENTATION:
            setExtOrientation(mHwcContext, inParcel->readInt32());
            break;
        case IQService::BUFFER_MIRRORMODE:
            setBufferMirrorMode(mHwcContext, inParcel->readInt32());
            break;
        case IQService::GET_DISPLAY_VISIBLE_REGION:
            ret = getDisplayVisibleRegion(mHwcContext, inParcel->readInt32(),
                                    outParcel);
            break;
        case IQService::CHECK_EXTERNAL_STATUS:
            isExternalConnected(mHwcContext, outParcel);
            break;
        case IQService::GET_DISPLAY_ATTRIBUTES:
            getDisplayAttributes(mHwcContext, inParcel, outParcel);
            break;
        case IQService::SET_HSIC_DATA:
            setHSIC(mHwcContext, inParcel);
        case IQService::PAUSE_WFD:
            pauseWFD(mHwcContext, inParcel->readInt32());
            break;
        default:
            ret = NO_ERROR;
    }
    return ret;
}



}
