/*
 *
 *    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.
 */

/**
 * @file ScreenManager.cpp
 *
 * Simple screen manager.
 *
 */

#include "ScreenManager.h"

#if CONFIG_HAVE_DISPLAY

#include <lib/support/CHIPMem.h>

#include <cassert>
#include <vector>

uint16_t ScreenFontHeight;
uint16_t ScreenTitleSafeTop;
uint16_t ScreenTitleSafeBottom;

color_t ScreenNormalColor = { 255, 255, 255 };
color_t ScreenFocusColor  = { 128, 128, 255 };
color_t ScreenButtonColor = { 64, 64, 64 };

namespace {

constexpr int kMainFont   = DEJAVU24_FONT;
constexpr int kButtonFont = DEJAVU18_FONT;

constexpr int kVLEDWidth  = 16;
constexpr int kVLEDHeight = 16;

SemaphoreHandle_t mutex;

struct Lock
{
    Lock() { xSemaphoreTakeRecursive(mutex, portMAX_DELAY); }
    ~Lock() { xSemaphoreGiveRecursive(mutex); }
};

struct VLED
{
    color_t color;
    color_t color_off;
    bool on;
    VLED(color_t color) : color(color), on(false)
    {
        color_off = color;
        color_off.r &= 0x1F;
        color_off.g &= 0x1F;
        color_off.b &= 0x1F;
    }
};

std::vector<VLED> vleds;

std::vector<Screen *> screens;

bool focusBack = false;

int lazyDisplay   = 0;
bool dirtyDisplay = false;

struct LazyDisplay
{
    LazyDisplay() { ++lazyDisplay; }
    ~LazyDisplay()
    {
        if (--lazyDisplay == 0)
        {
            if (dirtyDisplay)
            {
                ScreenManager::Display();
                dirtyDisplay = false;
            }
        }
    }
};

// Print text centered horizontally at x.
void PrintCentered(const char * s, int x, int y)
{
    TFT_print(s, x - (TFT_getStringWidth(s) / 2), y);
}

// Print button text in appropriate location (1 to 3).
void DisplayButtonText(int id, const char * s)
{
    tft_fg = ScreenButtonColor;
    int x  = (DisplayWidth / 2) + (id - 2) * (DisplayWidth * 3 / 10);
    PrintCentered(s, x, DisplayHeight - (ScreenTitleSafeBottom / 2)); // within ScreenTitleSafeBottom
}

void DisplayVLED(int id)
{
    TFT_fillRect(0, ScreenFontHeight * 3 / 2 + id * (kVLEDHeight + 2), kVLEDWidth, kVLEDHeight,
                 vleds[id].on ? vleds[id].color : vleds[id].color_off);
}

} // namespace

namespace ScreenManager {

void Init()
{
    mutex = xSemaphoreCreateRecursiveMutex();

    // https://github.com/loboris/ESP32_TFT_library/issues/48
    TFT_setFont(kButtonFont, nullptr);
    ScreenTitleSafeBottom = TFT_getfontheight() * 2;
    TFT_setFont(kMainFont, nullptr);
    ScreenFontHeight   = TFT_getfontheight();
    ScreenTitleSafeTop = ScreenFontHeight * 5 / 2;
}

void Display()
{
    Lock lock;

    if (lazyDisplay)
    {
        dirtyDisplay = true;
        return;
    }

    TFT_fillScreen(TFT_BLACK);
    TFT_setFont(kMainFont, nullptr);

    if (screens.empty())
    {
        tft_fg = TFT_RED;
        PrintCentered("No Screen", DisplayWidth / 2, DisplayHeight / 2);
        return;
    }

    if (screens.size() > 1)
    {
        tft_fg = focusBack ? ScreenFocusColor : ScreenNormalColor;
        TFT_print("<", ScreenFontHeight, ScreenFontHeight / 2);
    }

    std::string title = screens.back()->GetTitle();
    tft_fg            = ScreenNormalColor;
    TFT_print(title.c_str(), ScreenTitleSafeTop, ScreenFontHeight / 2); // within ScreenTitleSafeTop
    TFT_drawRect(ScreenTitleSafeTop, ScreenFontHeight * 3 / 2, TFT_getStringWidth(title.c_str()), 2, ScreenNormalColor);

    TFT_setFont(kButtonFont, nullptr);
    if (screens.back()->IsFocusable())
    {
        DisplayButtonText(1, screens.back()->GetButtonText(1).c_str());
        DisplayButtonText(2, screens.back()->GetButtonText(2).c_str());
    }
    if (focusBack)
    {
        DisplayButtonText(3, "Back");
    }
    else if (screens.back()->IsFocusable())
    {
        DisplayButtonText(3, screens.back()->GetButtonText(3).c_str());
    }
    TFT_setFont(kMainFont, nullptr);

    for (int i = 0; i < vleds.size(); ++i)
    {
        DisplayVLED(i);
    }

    screens.back()->Display();
}

void ButtonPressed(int id)
{
    Lock lock;
    LazyDisplay lazy;

    if (screens.empty())
    {
        return;
    }

    if (focusBack && id == 3)
    {
        PopScreen();
    }
    else if (screens.back()->IsFocusable())
    {
        switch (id)
        {
        case 1:
            focusBack = false;
            screens.back()->Focus(Screen::FocusType::PREVIOUS);
            break;
        case 2:
            focusBack = false;
            screens.back()->Focus(Screen::FocusType::NEXT);
            break;
        case 3:
            screens.back()->Action();
            break;
        }
        Display();
    }
}

void PushScreen(Screen * screen)
{
    Lock lock;
    LazyDisplay lazy;

    if (!screens.empty())
    {
        if (screens.back()->IsFocusable())
        {
            screens.back()->Focus(Screen::FocusType::BLUR);
        }
        screens.back()->Exit(false);
    }

    screen->Enter(true);       // screen is not top when enter/pushed
    screens.push_back(screen); // screen is pushed immediately after first enter

    focusBack = false;

    if (screens.back()->IsFocusable())
    {
        screens.back()->Focus(Screen::FocusType::NEXT);
    }
    else
    {
        focusBack = true;
    }

    Display();
}

void PopScreen()
{
    Lock lock;
    LazyDisplay lazy;

    if (screens.empty())
    {
        return;
    }

    Screen * screen = screens.back();
    screens.pop_back(); // screen is popped immediately before last exit
    screen->Exit(true); // screen is not top when exit/popped
    chip::Platform::Delete(screen);

    focusBack = false;

    if (!screens.empty())
    {
        screens.back()->Enter(false);
        if (screens.back()->IsFocusable())
        {
            screens.back()->Focus(Screen::FocusType::UNBLUR);
        }
        else
        {
            focusBack = true;
        }
    }

    Display();
}

void FocusBack()
{
    Lock lock;
    if (screens.size() > 1)
    {
        focusBack = true;
        if (screens.back()->IsFocusable())
        {
            screens.back()->Focus(Screen::FocusType::NONE);
        }
    }
    else
    {
        focusBack = false;
    }
}

int AddVLED(color_t color)
{
    Lock lock;
    int id = vleds.size();
    vleds.emplace_back(color);
    DisplayVLED(id);
    return id;
}

void SetVLED(int id, bool on)
{
    Lock lock;
    if (vleds[id].on == on)
    {
        return;
    }

    vleds[id].on = on;
    DisplayVLED(id);
    WakeDisplay();
}

void ToggleVLED(int id)
{
    Lock lock;
    vleds[id].on = !vleds[id].on;
    DisplayVLED(id);
    WakeDisplay();
}

} // namespace ScreenManager

#endif // CONFIG_HAVE_DISPLAY
