/*
// Copyright (c) 2014 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.
*/
#include <common/utils/HwcTrace.h>
#include <Hwcomposer.h>
#include <DisplayQuery.h>
#include <common/observers/SoftVsyncObserver.h>
#include <DummyDevice.h>

namespace android {
namespace intel {
DummyDevice::DummyDevice(uint32_t disp, Hwcomposer& hwc)
    : mInitialized(false),
      mConnected(false),
      mBlank(false),
      mDisp(disp),
      mHwc(hwc),
      mVsyncObserver(NULL),
      mName("Dummy")
{
    CTRACE();
}

DummyDevice::~DummyDevice()
{
    WARN_IF_NOT_DEINIT();
}

bool DummyDevice::prePrepare(hwc_display_contents_1_t *display)
{
    RETURN_FALSE_IF_NOT_INIT();

    if (!display) {
        return true;
    }

    // nothing need to do for dummy display
    return true;
}

bool DummyDevice::prepare(hwc_display_contents_1_t *display)
{
    RETURN_FALSE_IF_NOT_INIT();

    if (!display || mDisp >= DEVICE_VIRTUAL) {
        return true;
    }

    // skip all layers composition on dummy display
    if (display->flags & HWC_GEOMETRY_CHANGED) {
        for (size_t i=0; i < display->numHwLayers-1; i++) {
            hwc_layer_1 * player = &display->hwLayers[i];
            player->compositionType = HWC_OVERLAY;
            player->flags &= ~HWC_SKIP_LAYER;
        }
    }

    return true;
}

bool DummyDevice::commit(hwc_display_contents_1_t *display, IDisplayContext *context)
{
    RETURN_FALSE_IF_NOT_INIT();

    if (!display || !context)
        return true;

    // nothing need to do for dummy display
    return true;
}

bool DummyDevice::vsyncControl(bool enabled)
{
    RETURN_FALSE_IF_NOT_INIT();
    return mVsyncObserver->control(enabled);
}

bool DummyDevice::blank(bool blank)
{
    RETURN_FALSE_IF_NOT_INIT();

    mBlank = blank;

    return true;
}

bool DummyDevice::getDisplaySize(int *width, int *height)
{
    RETURN_FALSE_IF_NOT_INIT();
    if (!width || !height) {
        ELOGTRACE("invalid parameters");
        return false;
    }

    // TODO: make this platform specifc
    *width = 1280;//720;
    *height = 720;//1280;
    return true;
}

bool DummyDevice::getDisplayConfigs(uint32_t *configs,
                                         size_t *numConfigs)
{
    RETURN_FALSE_IF_NOT_INIT();
    if (!configs || !numConfigs) {
        ELOGTRACE("invalid parameters");
        return false;
    }

    if (!mConnected) {
        ILOGTRACE("dummy device is not connected");
        return false;
    }

    *configs = 0;
    *numConfigs = 1;

    return true;
}

bool DummyDevice::getDisplayAttributes(uint32_t configs,
                                            const uint32_t *attributes,
                                            int32_t *values)
{
    RETURN_FALSE_IF_NOT_INIT();

    if ((configs > 0) || !attributes || !values) {
        ELOGTRACE("invalid parameters");
        return false;
    }

    if (!mConnected) {
        ILOGTRACE("dummy device is not connected");
        return false;
    }

    int i = 0;
    while (attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE) {
        switch (attributes[i]) {
        case HWC_DISPLAY_VSYNC_PERIOD:
            values[i] = 1e9 / 60;
            break;
        case HWC_DISPLAY_WIDTH:
            values[i] = 1280;
            break;
        case HWC_DISPLAY_HEIGHT:
            values[i] = 720;
            break;
        case HWC_DISPLAY_DPI_X:
            values[i] = 0;
            break;
        case HWC_DISPLAY_DPI_Y:
            values[i] = 0;
            break;
        default:
            ELOGTRACE("unknown attribute %d", attributes[i]);
            break;
        }
        i++;
    }

    return true;
}

bool DummyDevice::compositionComplete()
{
    RETURN_FALSE_IF_NOT_INIT();
    return true;
}

bool DummyDevice::initialize()
{
    mInitialized = true;

    mVsyncObserver = new SoftVsyncObserver(*this);
    if (!mVsyncObserver || !mVsyncObserver->initialize()) {
        DEINIT_AND_RETURN_FALSE("Failed to create Soft Vsync Observer");
        mInitialized = false;
    }

    return mInitialized;
}

bool DummyDevice::isConnected() const
{
    return mConnected;
}

const char* DummyDevice::getName() const
{
    return "Dummy";
}

int DummyDevice::getType() const
{
    return mDisp;
}

void DummyDevice::onVsync(int64_t timestamp)
{
    if (!mConnected)
        return;

    mHwc.vsync(mDisp, timestamp);
}

void DummyDevice::dump(Dump& d)
{
    d.append("-------------------------------------------------------------\n");
    d.append("Device Name: %s (%s)\n", mName,
            mConnected ? "connected" : "disconnected");
}

void DummyDevice::deinitialize()
{
    DEINIT_AND_DELETE_OBJ(mVsyncObserver);
    mInitialized = false;
}

bool DummyDevice::setPowerMode(int /*mode*/)
{
    return true;
}

int DummyDevice::getActiveConfig()
{
    return 0;
}

bool DummyDevice::setActiveConfig(int /*index*/)
{
    return false;
}

} // namespace intel
} // namespace android
