/**
 * @file lcd_api.c
 * @brief LCD API implementation
 * @author Tim S.
 * @todo Implement function to read images from fs
 */
#include "lcd_api.h"

static const char* TAG = "lcd_api";

static DMA2D_HandleTypeDef hDma2dHandler2;

void lcd_init(bool bl_on) {
    LOG_INFO(TAG, "Init LCD");

    BSP_LCD_Init();
    BSP_LCD_LayerDefaultInit(1, LCD_FB_START_ADDRESS);
    BSP_LCD_LayerDefaultInit(0, LCD_FB_START_ADDRESS + (BSP_LCD_GetXSize()*BSP_LCD_GetYSize()*4));
    BSP_LCD_SelectLayer(0);
    BSP_LCD_Clear(LCD_COLOR_BLACK);
    BSP_LCD_SelectLayer(1);
    BSP_LCD_Clear(LCD_COLOR_BLACK);
    if (bl_on) {
        HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_SET);
        HAL_GPIO_WritePin(GPIOI, GPIO_PIN_12, GPIO_PIN_SET);
    } else {
    	HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_RESET);
    	HAL_GPIO_WritePin(GPIOI, GPIO_PIN_12, GPIO_PIN_RESET);
    }
}

void lcd_display_text(uint8_t* text, uint16_t x_pos, uint16_t y_pos, uint32_t color, uint32_t bg_color, sFONT *font) {
    LOG_INFO(TAG, "Display text: %s @x=%d,y=%d", text, x_pos, y_pos);

    uint16_t tot_length = x_pos + (strlen(text) * font->Width);
    if ((x_pos % font->Width) != 0) {
        x_pos -= (x_pos % font->Width);
    }

    BSP_LCD_SetTextColor(color);
    BSP_LCD_SetBackColor(bg_color);
    BSP_LCD_SetFont(font);

    if (tot_length > BSP_LCD_GetXSize()) {
        for (int i = 0; i < strlen(text); i++) {
            if ((x_pos) > BSP_LCD_GetXSize() - (font->Width)*2) {
                if (isalpha(text[i-1]) && isalpha(text[i])) {
                    BSP_LCD_DisplayChar(x_pos, y_pos, '-');
                    i -= 1;
                }
                x_pos = 0;
                y_pos += font->Height;
            } else {
                BSP_LCD_DisplayChar(x_pos, y_pos, text[i]);
                x_pos += font->Width;
            }
        }
    } else {
        BSP_LCD_DisplayStringAt(x_pos, y_pos, text, LEFT_MODE);
    }

}

void lcd_draw_bmp(const void* p_src, uint32_t x_pos, uint32_t y_pos, uint32_t x_size, uint32_t y_size, uint32_t color_mode) {

    uint32_t address = hLtdcHandler.LayerCfg[1].FBStartAdress + (((BSP_LCD_GetXSize()*y_pos) + x_pos)*(4));
    void *p_dst = (void *)address;


    hDma2dHandler2.Init.Mode         = DMA2D_M2M_PFC;
    hDma2dHandler2.Init.ColorMode    = DMA2D_ARGB8888;
    hDma2dHandler2.Init.OutputOffset = BSP_LCD_GetXSize()-x_size;

    hDma2dHandler2.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
    hDma2dHandler2.LayerCfg[1].InputAlpha = 0xFF;
    hDma2dHandler2.LayerCfg[1].InputColorMode = color_mode;
    hDma2dHandler2.LayerCfg[1].InputOffset = 0;

    LOG_INFO(TAG, "DMA2D init");
    hDma2dHandler2.Instance = DMA2D;
    if (HAL_DMA2D_Init(&hDma2dHandler2) != HAL_OK) {
        LOG_CRIT(TAG, "HAL_DMA2D_Init error");
        return;
    }
    LOG_INFO(TAG, "DMA2D config layer");
    if (HAL_DMA2D_ConfigLayer(&hDma2dHandler2, 1) != HAL_OK) {
    	LOG_CRIT(TAG, "HAL_DMA2D_ConfigLayer error");
        return;
    }
    LOG_INFO(TAG, "DMA2D start");
    if (HAL_DMA2D_Start(&hDma2dHandler2, (uint32_t)p_src, (uint32_t)p_dst, x_size, y_size) != HAL_OK) {
        LOG_CRIT(TAG, "HAL_DMA2D_Start error");
        return;
    }
    LOG_INFO(TAG, "DMA2D poll");
    HAL_DMA2D_PollForTransfer(&hDma2dHandler2, 10);
}
