/******************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Quick Ultralite module.
**
** $QT_BEGIN_LICENSE:COMM$
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** $QT_END_LICENSE$
**
******************************************************************************/

#include "lcdifv2layerengine.h"
#include "display_support.h"
#include <platforminterface/log.h>
#include <platforminterface/allocator.h>
#include "platform/mem.h"
#include "vglitesupport.h"
#include "lcdifv2layer.h"
#include "fsl_lcdifv2.h"

using namespace Qul::Platform::Private;
using namespace Qul::PlatformInterface;

Lcdif2LayerEngine::Lcdif2LayerEngine()
{
    BOARD_PrepareDisplayController();

    auto status = g_dc.ops->init(&g_dc);
    if (kStatus_Success != status) {
        Qul::PlatformInterface::log("Display initialization failed\r\n");
        assert(0);
    }

    if (!Private::Vglite::init()) {
        Qul::PlatformInterface::log("Unable to initialize vg_lite\r\n");
        std::terminate();
    }
}

LayerEngine::ItemLayer *Lcdif2LayerEngine::allocateItemLayer(const Screen *screen,
                                                             const ItemLayerProperties &props,
                                                             SpriteLayer *spriteLayer)
{
    if (Lcdifv2Layer::full() || !Lcdifv2Layer::valid(screen, props.size)) {
        return nullptr;
    }

    auto l = qul_new<Lcdifv2ItemLayer>(screen, props);
    if (spriteLayer && l) {
        auto s = reinterpret_cast<Lcdifv2Sprite *>(spriteLayer);
        s->registerObserver(l);
    }
    return l;
}

LayerEngine::ImageLayer *Lcdif2LayerEngine::allocateImageLayer(
    const Qul::PlatformInterface::Screen *screen,
    const Qul::PlatformInterface::LayerEngine::ImageLayerProperties &props,
    Qul::PlatformInterface::LayerEngine::SpriteLayer *spriteLayer)
{
    if (Lcdifv2Layer::full() || !Lcdifv2Layer::valid(screen, props.texture.size())) {
        return nullptr;
    }

    auto l = qul_new<Lcdifv2ImageLayer>(screen, props);
    if (spriteLayer && l) {
        auto s = reinterpret_cast<Lcdifv2Sprite *>(spriteLayer);
        s->registerObserver(l);
    }
    return l;
}

LayerEngine::SpriteLayer *Lcdif2LayerEngine::allocateSpriteLayer(const Screen *screen,
                                                                 const SpriteLayerProperties &props)
{
    if (Lcdifv2Layer::full()) {
        return nullptr;
    }

    return qul_new<Lcdifv2Sprite>(props);
}

void Lcdif2LayerEngine::deallocateItemLayer(ItemLayer *layer)
{
    qul_delete(reinterpret_cast<Lcdifv2ItemLayer *>(layer));
}

void Lcdif2LayerEngine::deallocateImageLayer(ImageLayer *layer)
{
    qul_delete(reinterpret_cast<Lcdifv2ImageLayer *>(layer));
}

void Lcdif2LayerEngine::deallocateSpriteLayer(SpriteLayer *layer)
{
    qul_delete(reinterpret_cast<Lcdifv2Sprite *>(layer));
}

void Lcdif2LayerEngine::updateItemLayer(ItemLayer *layer, const ItemLayerProperties &props)
{
    if (layer) {
        auto l = reinterpret_cast<Lcdifv2ItemLayer *>(layer);
        l->update(props);
    }
}

void Lcdif2LayerEngine::updateImageLayer(ImageLayer *layer, const ImageLayerProperties &props)
{
    if (layer) {
        auto l = reinterpret_cast<Lcdifv2ImageLayer *>(layer);
        l->update(props);
    }
}

void Lcdif2LayerEngine::updateSpriteLayer(SpriteLayer *layer, const SpriteLayerProperties &props)
{
    if (layer) {
        auto l = reinterpret_cast<Lcdifv2Sprite *>(layer);
        l->update(props);
    }
}

void Lcdif2LayerEngine::commit()
{
    Lcdifv2Layer::flush();
}