#include "main_window.hpp"

#include <QtGlobal>

MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), m_currentIcon(0), m_visibility(true)
{
    qDebug("Creating main window");

    m_ui.setupUi(this);

    loadIcons();

    if(!QSystemTrayIcon::isSystemTrayAvailable()) {
        qWarning("System tray is not available -> tray icon will be disabled");
    }
    else {
        qDebug("System tray is available");

        m_trayIconMenu = new QMenu(this);
        m_showHideAction = m_trayIconMenu->addAction(tr("Hide"), [this]() {
            if(m_visibility) {
                m_showHideAction->setText(tr("Show"));
                hide();
            }
            else {
                m_showHideAction->setText(tr("Hide"));
                show();
            }
            m_visibility = !m_visibility;
        });
        m_trayIconMenu->addSeparator();
        m_trayIconMenu->addAction(tr("Quit"), this, &QWidget::close);

        qDebug("Tray icon context menu initialized");

        m_trayIcon = new QSystemTrayIcon(this);
        m_trayIcon->setIcon(*m_errorIcon);
        m_trayIcon->setContextMenu(m_trayIconMenu);
        m_trayIcon->show();

        qDebug("Tray icon initialized");
    }

    m_timer = new QTimer(this);
    connect(m_timer, &QTimer::timeout, this, &MainWindow::nextIcon);
    m_timer->start(500);

    qDebug("Tray icon update timer started");
}

MainWindow::~MainWindow()
{
    qDebug("Destroying main window");
}

namespace {

template<typename>
struct array_size;

template<typename T, size_t N>
struct array_size<std::array<T, N>> {
    static constexpr auto value = N;
};

template<typename T>
inline constexpr auto array_size_v = array_size<T>::value;

} // namespace

void MainWindow::loadIcons()
{
    qDebug("Loading icons");

    constexpr auto NO_SENSOR_ICON_PATHS = std::array{
        ":/AdaptiveBrightness/resources/nosense_0.ico", ":/AdaptiveBrightness/resources/nosense_1.ico", ":/AdaptiveBrightness/resources/nosense_2.ico",
        ":/AdaptiveBrightness/resources/nosense_3.ico", ":/AdaptiveBrightness/resources/nosense_4.ico", ":/AdaptiveBrightness/resources/nosense_5.ico",
        ":/AdaptiveBrightness/resources/nosense_6.ico", ":/AdaptiveBrightness/resources/nosense_7.ico", ":/AdaptiveBrightness/resources/nosense_8.ico",
    };

    static_assert(NO_SENSOR_ICON_PATHS.size() == array_size_v<decltype(m_noSensorStateIcons)>, "Number of paths does not match number of icons");

    constexpr auto SENSOR_ICON_PATHS = std::array{
        ":/AdaptiveBrightness/resources/sense_0.ico", ":/AdaptiveBrightness/resources/sense_1.ico", ":/AdaptiveBrightness/resources/sense_2.ico",
        ":/AdaptiveBrightness/resources/sense_3.ico", ":/AdaptiveBrightness/resources/sense_4.ico", ":/AdaptiveBrightness/resources/sense_5.ico",
        ":/AdaptiveBrightness/resources/sense_6.ico", ":/AdaptiveBrightness/resources/sense_7.ico", ":/AdaptiveBrightness/resources/sense_8.ico",
    };

    static_assert(SENSOR_ICON_PATHS.size() == array_size_v<decltype(m_sensorStateIcons)>, "Number of paths does not match number of icons");

    constexpr auto ERROR_ICON_PATH = ":/AdaptiveBrightness/resources/error.ico";

    for(std::size_t i = 0; i < NO_SENSOR_ICON_PATHS.size(); ++i) {
        m_noSensorStateIcons[i] = std::make_unique<QIcon>(NO_SENSOR_ICON_PATHS[i]);
    }

    for(std::size_t i = 0; i < SENSOR_ICON_PATHS.size(); ++i) {
        m_sensorStateIcons[i] = std::make_unique<QIcon>(SENSOR_ICON_PATHS[i]);
    }

    m_errorIcon = std::make_unique<QIcon>(ERROR_ICON_PATH);

    qDebug("Icons loaded");
}

void MainWindow::nextIcon()
{
    qDebug("Cycling to next icon");

    if(!m_trayIcon) {
        qWarning("Cannot cycle through tray icons, because no tray icon is available");
        return;
    }

    m_currentIcon = (m_currentIcon + 1) % m_noSensorStateIcons.size();
    m_trayIcon->setIcon(*m_noSensorStateIcons[m_currentIcon]);
}
