/*
Copyright (c) 2006-2009, Tom Thielicke IT Solutions

SPDX-License-Identifier: GPL-2.0-only
*/

/****************************************************************
**
** Implementation of the KeyBoard class
** File name: numpad.cpp
**
****************************************************************/

#include <QCoreApplication>
#include <QPainter>
#include <QPen>
#include <QSettings>

#include "../def/defines.h"
#include "errormessage.h"
#include "numpad.h"

NumPad::NumPad(QWidget* parent)
    : QWidget(parent)
    , isStarted(false)
    , isPaused(false)
    , keyLayoutFound(false) // Flag whether the key properties where found
    , activeKey('0')
    , activeX(0)
    , activeY(0)
    , activeColor(0)
    , activeForm(0)
    , activeFinger(8)
{
    // Read settings (keyboard layout and key coloring)
    readSettings();

    // Load all images used in the keyboard
    loadKeyImages();

    colorIndex[0] = 4; // yellow
    colorIndex[1] = 3; // green
    colorIndex[2] = 2; // blue
    colorIndex[3] = 1; // red
    colorIndex[4] = 0; // grey (no additional key)

    keyColors[0] = QColor(253, 232, 151);
    keyColors[1] = QColor(181, 235, 157);
    keyColors[2] = QColor(172, 215, 254);
    keyColors[3] = QColor(249, 174, 174);

    currentPen.setWidth(3);
    currentPen.setStyle(Qt::DotLine);

    // Sql class to get the key layout of a given char
    keyboardSql = new KeyboardSql(layout);
    // Fix the size of this class because of using fix sized images
    setFixedSize(180, 228);
    setAttribute(Qt::WA_NoSystemBackground);
}

void NumPad::startBoard()
{
    // Turn start flag true
    isStarted = true;
    // Turn pause flag false
    isPaused = false;
    // Call the paint event (refresh the keyboard)
    repaint();
}

void NumPad::pauseBoard()
{
    // Turn start flag false
    isStarted = false;
    // Turn pause flag true
    isPaused = true;
    // Call the paint event (refresh the keyboard)
    update();
}

void NumPad::stopBoard()
{
    // Turn start flag false
    isStarted = false;
    // Call the paint event (refresh the keyboard)
    update();
}

void NumPad::paintEvent([[maybe_unused]] QPaintEvent* event)
{
    // Draw empty grey keyboard
    cleanKeyboard();

    if (isStarted) {
        // Color current key and modifier
        colorKey();
    }
    // Draw keyboard labeling
    drawLayout();
}

void NumPad::loadKeyImages()
{
    // Load background
    if (!loadImage(background, ":/img/numpadbg.png")) {
        return;
    }
    // Keys
    // -> four different key colors
    for (int x = 0; x < 5; x++) {
        // -> six different key forms
        for (int y = 0; y < 10; y++) {
            // Load key
            if (!loadImage(keyImage[x][y],
                    ":/img/key" + QString::number(x) + "_" + QString::number(y)
                        + ".png")) {
                return;
            }
        }
    }
    // Load key labeling
    if (!loadImage(keyLayout,
            ":/img/" + layout.left(2) + "_numpad_" + layout.right(3)
                + ".png")) {

        return;
    }
}

bool NumPad::loadImage(QPixmap& img, QString filename)
{
    // Check whether loading the image is correct
    if (!img.load(filename)) {
        // Error message
        ErrorMessage* errorMessage = new ErrorMessage(this);
        errorMessage->showMessage(Error::key_pic, ErrorMessage::Type::Warning,
            ErrorMessage::Cancel::Operation, filename);
        return false;
    }
    return true;
}

void NumPad::cleanKeyboard()
{
    QPainter painter(this);
    // Background image
    painter.drawPixmap(0, 0, background);

    // Keys first row
    for (int i = 0; i < 4; i++) {
        painter.drawPixmap(10 + (40 * i), 15, keyImage[0][0]);
    }

    // Keys second row
    for (int i = 0; i < 3; i++) {
        painter.drawPixmap(10 + (40 * i), 55, keyImage[0][0]);
    }
    if (!isMac) {
        painter.drawPixmap(130, 55, keyImage[0][9]);
    } else {
        painter.drawPixmap(130, 55, keyImage[0][0]);
    }

    // Keys third row
    for (int i = 0; i < 3; i++) {
        painter.drawPixmap(10 + (40 * i), 95, keyImage[0][0]);
    }
    if (layout.right(3) == "mac") {
        painter.drawPixmap(130, 95, keyImage[0][0]);
    }

    // Keys fourth row
    for (int i = 0; i < 3; i++) {
        painter.drawPixmap(10 + (40 * i), 135, keyImage[0][0]);
    }
    painter.drawPixmap(130, 135, keyImage[0][9]);

    // Keys fifth row
    painter.drawPixmap(10, 175, keyImage[0][7]);
    painter.drawPixmap(90, 175, keyImage[0][0]);
}

void NumPad::drawLayout()
{
    QPainter painter(this);
    // Draw the labeling of the keyboard
    painter.drawPixmap(10, 15, keyLayout);
}

// Places the current colored keys
void NumPad::colorKey()
{
    QPainter painter(this);

    if (keyLayoutFound) {

        if (keyColoring) {
            // Color current key
            painter.drawPixmap(activeX, activeY,
                keyImage[colorIndex[4 - activeColor]][activeForm]);
        }
    }
}

void NumPad::setKey(QChar key)
{
    QString statusText = "0";

    // Check whether key is already colored and whether keyboard is started
    if (activeKey != key && isStarted) {
        activeFinger = 8;
        // New current key
        activeKey = key;
        // Get the properties of the key
        // If false, no properties were found
        keyLayoutFound = keyboardSql->getNumLayout(activeKey, &activeX,
            &activeY, &activeColor, &activeForm, &activeFinger, &statusText);
        // Emit the help text of current key(s)
        emit statusRefreshed(statusText);
        // Call the paint event (refresh the keyboard)
        if (keyColoring) {
            repaint();
        }
    }
}

void NumPad::readSettings()
{
#if APP_PORTABLE
    QSettings settings(
        QCoreApplication::applicationDirPath() + "/portable/settings.ini",
        QSettings::IniFormat);
#else
    QSettings settings;
#endif
    // Check user's keyboard layout
    settings.beginGroup("main");
    layout = settings.value("language_layout", t10::app_std_language_layout)
                 .toString();
    settings.endGroup();
    // Check if key coloring is turned on
    settings.beginGroup("support");
    keyColoring = settings.value("check_selection", true).toBool();
    settings.endGroup();
}
