/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    All rights reserved.
 *
 *    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 <stdio.h>
#include <string.h>

#include "ThermostatUI.h"
#include "demo-ui-bitmaps.h"
#include "dmd.h"
#include "glib.h"
#include "lcd.h"

// LCD line define
constexpr uint8_t kTempLcdInitialX = 30;

// Bitmap
static const uint8_t silabsLogo[]       = { SILABS_LOGO_SMALL };
static const uint8_t matterLogoBitmap[] = { MATTER_LOGO_BITMAP };

static const uint8_t wifiLogo[]   = { WIFI_BITMAP };
static const uint8_t threadLogo[] = { THREAD_BITMAP };
static const uint8_t bleLogo[]    = { BLUETOOTH_ICON_SMALL };

static const unsigned char monaco_48pt[]          = { MONACO_48PT };
static const unsigned char heating_bits[]         = { HEATING_BITMAP };
static const unsigned char cooling_bits[]         = { COOLING_BITMAP };
static const unsigned char heating_cooling_bits[] = { HEATING_COOLING_BITMAP };

static int8_t mHeatingCelsiusSetPoint;
static int8_t mCoolingCelsiusSetPoint;
static int8_t mCurrentTempCelsius;
static uint8_t mMode;

#ifdef SL_WIFI
#define UI_WIFI 1
#else
#define UI_WIFI 0
#endif

void ThermostatUI::DrawUI(GLIB_Context_t * glibContext)
{
    if (glibContext == nullptr)
    {
        SILABS_LOG("Context is null");
        return;
    }

    GLIB_clear(glibContext);
    DrawHeader(glibContext);
    DrawCurrentTemp(glibContext, mCurrentTempCelsius);
    DrawFooter(glibContext, false);

    DMD_updateDisplay();
}

void ThermostatUI::SetHeatingSetPoint(int8_t temp)
{
    mHeatingCelsiusSetPoint = temp;
}

void ThermostatUI::SetCoolingSetPoint(int8_t temp)
{
    mCoolingCelsiusSetPoint = temp;
}

void ThermostatUI::SetCurrentTemp(int8_t temp)
{
    mCurrentTempCelsius = temp;
}
void ThermostatUI::SetMode(uint8_t mode)
{
    mMode = mode;
}

void ThermostatUI::DrawHeader(GLIB_Context_t * glibContext)
{
    // Draw Silabs Corner icon
    GLIB_drawBitmap(glibContext, SILABS_ICON_POSITION_X, STATUS_ICON_LINE, SILABS_LOGO_WIDTH, SILABS_LOGO_HEIGHT, silabsLogo);
    // Draw BLE Icon
    GLIB_drawBitmap(glibContext, BLE_ICON_POSITION_X, STATUS_ICON_LINE, BLUETOOTH_ICON_SIZE, BLUETOOTH_ICON_SIZE, bleLogo);
    // Draw WiFi/OpenThread Icon
    GLIB_drawBitmap(glibContext, NETWORK_ICON_POSITION_X, STATUS_ICON_LINE, (UI_WIFI) ? WIFI_BITMAP_HEIGHT : THREAD_BITMAP_WIDTH,
                    WIFI_BITMAP_HEIGHT, (UI_WIFI) ? wifiLogo : threadLogo);
    // Draw Matter Icon
    GLIB_drawBitmap(glibContext, MATTER_ICON_POSITION_X, STATUS_ICON_LINE, MATTER_LOGO_WIDTH, MATTER_LOGO_HEIGHT, matterLogoBitmap);
    DMD_updateDisplay();
}

void ThermostatUI::DrawFooter(GLIB_Context_t * glibContext, bool autoMode)
{
    switch (static_cast<ThermostatUI::HVACMode>(mMode))
    {
    case HVACMode::HEATING:
        GLIB_drawStringOnLine(glibContext, "Mode : Heating", 11, GLIB_ALIGN_LEFT, 0, 0, true);
        GLIB_drawBitmap(glibContext, HEATING_COOLING_X, HEATING_COOLING_Y, COOLING_WIDTH, COOLING_HEIGHT, heating_bits);
        DrawSetPoint(glibContext, mHeatingCelsiusSetPoint, false);
        break;
    case HVACMode::COOLING:
        GLIB_drawStringOnLine(glibContext, "Mode : Cooling", 11, GLIB_ALIGN_LEFT, 0, 0, true);
        GLIB_drawBitmap(glibContext, HEATING_COOLING_X, HEATING_COOLING_Y, COOLING_WIDTH, COOLING_HEIGHT, cooling_bits);
        DrawSetPoint(glibContext, mCoolingCelsiusSetPoint, false);
        break;
    case HVACMode::HEATING_COOLING:
        GLIB_drawStringOnLine(glibContext, "Mode : Auto", 11, GLIB_ALIGN_LEFT, 0, 0, true);
        GLIB_drawBitmap(glibContext, HEATING_COOLING_X, HEATING_COOLING_Y, COOLING_WIDTH, COOLING_HEIGHT, heating_cooling_bits);
        DrawSetPoint(glibContext, mHeatingCelsiusSetPoint, false);
        DrawSetPoint(glibContext, mCoolingCelsiusSetPoint, true);
        break;
    case HVACMode::MODE_OFF:
        DrawSetPoint(glibContext, 0, false);
        GLIB_drawStringOnLine(glibContext, "Mode : OFF", 11, GLIB_ALIGN_LEFT, 0, 0, true);
        break;
    default:
        break;
    }

    DMD_updateDisplay();
}

/**
 * @brief Draw a 2 digit Temp of screen. Because of this Celsius is used by default
 * @param GLIB_Context_t * pointer to the context for the GLIB library
 * @param int8_t current Temperature in Celsius
 * @param int8_t setPoint in Celsius
 * @param bool isCelsius By default set to True. For future development
 */
void ThermostatUI::DrawCurrentTemp(GLIB_Context_t * glibContext, int8_t temp, bool isCelsius)
{
    uint8_t tempArray[2];
    uint8_t position_x = 10;
    uint8_t * data;

    if (temp > 99 || temp < -99)
    {
        // Invalid temp for a house thermostat
        return;
    }

    if (temp < 0)
    {
        for (uint8_t y = 60; y < 64; y++)
        {
            for (uint8_t x = 1; x < 10; x++)
            {
                GLIB_drawPixel(glibContext, x, y);
            }
        }

        temp = temp * -1;
    }

    // Draw Unit
    if (isCelsius)
    {
        data = (uint8_t *) &monaco_48pt[DEGREE_INDEX];
        DrawFont(glibContext, 65, kTempLcdInitialX, 15, data, MONACO_FONT_CH_LENGTH);
        data = (uint8_t *) &monaco_48pt[CELSIUS_INDEX];
        DrawFont(glibContext, 70, kTempLcdInitialX, 15, data, MONACO_FONT_CH_LENGTH);
    }
    else
    {
        data = (uint8_t *) &monaco_48pt[DEGREE_INDEX];
        DrawFont(glibContext, 65, 25, 15, data, MONACO_FONT_CH_LENGTH); // 25 to fit with f of fahrenheint
        data = (uint8_t *) &monaco_48pt[FAHRENHEIT_INDEX];
        DrawFont(glibContext, 70, kTempLcdInitialX, 15, data, MONACO_FONT_CH_LENGTH);
    }

    // Print Current temp
    tempArray[0] = (uint8_t)((temp / 10));
    tempArray[1] = (uint8_t)((temp % 10));

    for (uint8_t ch = 0; ch < 2; ch++)
    {
        data = (uint8_t *) &monaco_48pt[tempArray[ch] * MONACO_FONT_NB_LENGTH];
        DrawFont(glibContext, position_x, kTempLcdInitialX, MONACO_FONT_WIDTH, data, MONACO_FONT_NB_LENGTH);
        position_x += MONACO_FONT_WIDTH;
    }
}

void ThermostatUI::DrawFont(GLIB_Context_t * glibContext, uint8_t initial_x, uint8_t initial_y, uint8_t width, uint8_t * data,
                            uint32_t size)
{
    uint8_t x = initial_x, y = initial_y;
    for (uint16_t i = 0; i < size; i++)
    {
        for (uint8_t mask = 0; mask < 8; mask++)
        {
            if (!(data[i] & (0x01 << mask)))
            {
                GLIB_drawPixel(glibContext, x, y);
            }
            // Check line changes
            if (((x - initial_x) % width) == 0 && x != initial_x)
            {
                x = initial_x;
                y++;
                // Font is 8 bit align with paddings bits;
                mask = 8;
            }
            else
            {
                x++;
            }
        }
    }
}

void ThermostatUI::DrawSetPoint(GLIB_Context_t * glibContext, int8_t setPoint, bool secondLine)
{
    char setPointLine[] = { '-', 'X', 'X', '\0' };

    if (setPoint > 99 || setPoint < -99)
    {
        return;
    }

    // Update SetPoint string
    if (static_cast<ThermostatUI::HVACMode>(mMode) == ThermostatUI::HVACMode::MODE_OFF)
    {
        setPointLine[0] = '-';
        setPointLine[1] = '-';
        setPointLine[2] = '\0';
    }
    else if (setPoint < 0)
    {
        setPointLine[0] = (setPoint < 0) ? '-' : ' ';
        setPoint *= -1;
        setPointLine[1] = ((setPoint / 10) + 0x30);
        setPointLine[2] = ((setPoint % 10) + 0x30);
    }
    else
    {
        setPointLine[0] = ((setPoint / 10) + 0x30);
        setPointLine[1] = ((setPoint % 10) + 0x30);
        setPointLine[2] = '\0';
    }

    // Print SetPoint
    GLIB_drawStringOnLine(glibContext, setPointLine, (secondLine) ? 8 : 7, GLIB_ALIGN_LEFT, 67, 0, true);
}
