/**
    \author mean fixounet@free.fr 2010
*/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "ADM_inttype.h" /* must be included prior to Qt headers for VC++ */

#include <QPaintEngine>
#include <QPainter>
// clang format-off
#include "ADM_default.h"
#include "config.h"

#include "ADM_default.h"
#include "DIA_coreToolkit.h"
//
#include "GUI_accelRender.h"
#include "GUI_render.h"
#include "GUI_renderInternal.h"
#include "GUI_simpleRender.h"
// clang format-on
#include "GUI_nullRender.h"
#define SIMPLE_RENDER_SWSCALE_RESIZE
#define SIMPLE_RENDER_TARGET_SIZE_IN_DEVICE_PIXELS

extern void *MUI_getDrawWidget(void);

VideoRenderBase *spawnSimpleRender()
{
    return new simpleRender();
    // return new nullRender();
}

/**
    \fn simpleRender
*/
simpleRender::simpleRender()
{
    ADM_info("creating simple render.\n");
    videoBuffer = NULL;
    paintEngineType = -1;
    videoWidget = NULL;
}
/**
    \fn simpleRender
*/
simpleRender::~simpleRender()
{
    admScopedMutex autoLock(&lock);
    videoWidget->setDrawer(NULL);
    videoWidget->useExternalRedraw(true);
    ADM_info("Destroying simple render.\n");
    if (videoBuffer)
        delete[] videoBuffer;
    videoBuffer = NULL;
}

/**
    \fn stop
*/
bool simpleRender::stop(void)
{
    ADM_info("stopping simple render.\n");
    return true;
}
/**
    \fn refresh
*/
bool simpleRender::refresh(void)
{
    videoWidget->repaint();
    return true;
}
/**
    \fn displayImage
*/
bool simpleRender::displayImage(ADMImage *pic)
{
    scaler->convertImage(pic, videoBuffer);
    lock.lock();
#ifdef SIMPLE_RENDER_SWSCALE_RESIZE
    int stride = ADM_IMAGE_ALIGN(displayWidth * 4);
    myImage = QImage(videoBuffer, displayWidth, displayHeight, stride, QImage::Format_RGB32)
                  .copy(0, 0, displayWidth, displayHeight);
#else
    int stride = ADM_IMAGE_ALIGN(imageWidth * 4);
    myImage =
        QImage(videoBuffer, imageWidth, imageHeight, stride, QImage::Format_RGB32).copy(0, 0, imageWidth, imageHeight);
#endif
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
    myImage.setDevicePixelRatio(info.scalingFactor);
#endif
    lock.unlock();
    refresh();
    return true;
}
// #if (ADM_UI_TYPE_BUILD == ADM_UI_QT4)
#define IVERT ADM_PIXFRMT_BGR32A
// #else
//     #define IVERT ADM_COLOR_RGB32A
// #endif
/**
    \fn cleanup
*/
bool simpleRender::cleanup(void)
{
    if (videoBuffer)
        delete[] videoBuffer;
    videoBuffer = NULL;
    if (scaler)
        delete scaler;
    scaler = NULL;
    return true;
}
/**
    \fn allocateStuff
*/
bool simpleRender::allocateStuff(void)
{
    cleanup();
#ifdef SIMPLE_RENDER_SWSCALE_RESIZE
    scaler = new ADMColorScalerFull(ADM_CS_BICUBIC, imageWidth, imageHeight, displayWidth, displayHeight,
                                    ADM_PIXFRMT_YV12, IVERT);
    uint32_t sz = ADM_IMAGE_ALIGN(displayWidth * 4);
    sz *= displayHeight;
#else
    scaler = new ADMColorScalerFull(ADM_CS_BICUBIC, imageWidth, imageHeight, imageWidth, imageHeight, ADM_PIXFRMT_YV12,
                                    IVERT);
    uint32_t sz = ADM_IMAGE_ALIGN(imageWidth * 4);
    sz *= imageHeight;
#endif
    videoBuffer = new uint8_t[sz];
    return true;
}

/**
    \fn changeZoom
*/
bool simpleRender::changeZoom(float newZoom)
{
    ADM_info("changing zoom, simple render.\n");
    calcDisplayFromZoom(newZoom);
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
#ifdef SIMPLE_RENDER_TARGET_SIZE_IN_DEVICE_PIXELS
    displayWidth *= info.scalingFactor;
    displayHeight *= info.scalingFactor;
#endif
#endif
    currentZoom = newZoom;
#ifdef SIMPLE_RENDER_SWSCALE_RESIZE
    allocateStuff();
#endif
    return true;
}
/**
    \fn changeZoom
*/
bool simpleRender::init(GUI_WindowInfo *window, uint32_t w, uint32_t h, float zoom)
{
    info = *window;
    baseInit(w, h, zoom);
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
#ifdef SIMPLE_RENDER_TARGET_SIZE_IN_DEVICE_PIXELS
    displayWidth *= info.scalingFactor;
    displayHeight *= info.scalingFactor;
#endif
#endif
    ADM_info("init, simple render. w=%d, h=%d,zoom=%.4f\n", (int)w, (int)h, zoom);
    allocateStuff();
    videoWidget = (ADM_Qvideo *)info.widget;
    videoWidget->useExternalRedraw(false);
    videoWidget->setDrawer(this);
    return true;
}

/**
 * \brief This is the callback called when the display wants to redraw
 * @param widget
 * @param ev
 * @return
 */
bool simpleRender::draw(QWidget *widget, QPaintEvent *ev)
{
    admScopedMutex autoLock(&lock);
    QPainter painter(widget);
    if (painter.isActive())
    {
        const QRect rec = ev->rect();
        painter.drawImage(rec, myImage);
    }
    else
    {
        ADM_warning("Painter inactive!\n");
    }
    return true;
}
