#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QFileDialog>
#include <QIcon>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QGuiApplication::setWindowIcon(QIcon("logo.png"));
    QAction *actionLoad = new QAction(tr("Load"), this);
    ui->menuLoad->addAction(actionLoad);

    executor = new Executor(&machine);
    executorThread = new QThread(this);

    executor->moveToThread(executorThread);

    connect(this, &MainWindow::startExecutor, executor, &Executor::start, Qt::QueuedConnection);
    connect(this, &MainWindow::stopExecutor,  executor, &Executor::stop,  Qt::QueuedConnection);
    connect(this, &MainWindow::stepExecutor,  executor, &Executor::step,  Qt::QueuedConnection);

    connect(executor, &Executor::updateRequested, this, &MainWindow::updateUI, Qt::QueuedConnection);
    connect(executor, &Executor::signalStarted, this, &MainWindow::setStatusLightRunning, Qt::QueuedConnection);
    connect(executor, &Executor::signalStopped, this, &MainWindow::setStatusLightStopped, Qt::QueuedConnection);
    connect(executor, &Executor::signalEnded, this, &MainWindow::setStatusLightEnded, Qt::QueuedConnection);

    executorThread->start();

    connect(ui->menuVizitka, &QMenu::aboutToShow, this, &MainWindow::on_menuVizitka_triggered);

    connect(actionLoad, &QAction::triggered, this, &MainWindow::onLoadTriggered);
    //connect(ui->runButton, &QPushButton::clicked, this, &MainWindow::on_runButton_clicked);
    //connect(ui->stepButton, &QPushButton::clicked, this, &MainWindow::on_stepButton_clicked);

    updateUI();
    ui->statusLight->setFixedSize(16,16);
    ui->statusLight->setStyleSheet("background-color: green; border-radius: 8px;");

    // nastavi tabelo
    const int columns = 16;
    int memSize = machine.getMemSize(); // ali fiksno (npr. 1000000), če še ni naloženo
    int rows = (memSize + columns - 1) / columns;

    ui->tableWidget->setColumnCount(columns);
    ui->tableWidget->setRowCount(rows);

    // Nastavi naslove stolpcev
    QStringList headers;
    for (int c = 0; c < columns; ++c) {
        headers << QString("%1").arg(c, 2, 16, QChar('0')).toUpper();
    }
    ui->tableWidget->setHorizontalHeaderLabels(headers);

    // Nastavi naslove vrstic v heks formatu
    QStringList verticalHeaders;
    for (int r = 0; r < rows; ++r) {
        verticalHeaders << QString("%1").arg(r * columns, 4, 16, QChar('0')).toUpper();
    }
    ui->tableWidget->setVerticalHeaderLabels(verticalHeaders);

    // Nastavi fiksno širino stolpcev (ali prilagodi po potrebi)
    int columnWidth = 30;
    for (int c = 0; c < columns; ++c) {
        ui->tableWidget->setColumnWidth(c, columnWidth);
    }

    // Nastavi politiko velikosti
    ui->tableWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
}

MainWindow::~MainWindow()
{
    executorThread->quit();
    executorThread->wait();
    delete executor;
    delete ui;
}

void populateMemoryTable(QTableWidget* tableWidget, Machine& machine) {
    const int columns = 16;
    int memSize = machine.getMemSize();

    for (int r = 0; r < tableWidget->rowCount(); ++r) {
        for (int c = 0; c < columns; ++c) {
            int addr = r * columns + c;
            if (addr < memSize) {
                unsigned char val = machine.readByte(addr);
                QString hexVal = QString("%1").arg(val, 2, 16, QChar('0')).toUpper();
                // Posodobi ali ustvari nov element
                if (tableWidget->item(r, c)) {
                    tableWidget->item(r, c)->setText(hexVal);
                } else {
                    tableWidget->setItem(r, c, new QTableWidgetItem(hexVal));
                }
            }
        }
    }
}

void MainWindow::updateRegisters()
{
    ui->labelA->setText(QString("0x%1").arg(machine.getA(), 6, 16, QChar('0')).toUpper());
    ui->labelX->setText(QString("0x%1").arg(machine.getX(), 6, 16, QChar('0')).toUpper());
    ui->labelL->setText(QString("0x%1").arg(machine.getL(), 6, 16, QChar('0')).toUpper());
    ui->labelB->setText(QString("0x%1").arg(machine.getB(), 6, 16, QChar('0')).toUpper());
    ui->labelS->setText(QString("0x%1").arg(machine.getS(), 6, 16, QChar('0')).toUpper());
    ui->labelT->setText(QString("0x%1").arg(machine.getT(), 6, 16, QChar('0')).toUpper());
    ui->labelPC->setText(QString("0x%1").arg(machine.getPC(), 6, 16, QChar('0')).toUpper());
    ui->labelSW->setText(QString("0x%1").arg(machine.getSW(), 6, 16, QChar('0')).toUpper());

    // F je float/double register
    ui->labelF->setText(QString::number(machine.getF()));
}

void MainWindow::updateUI()
{
    updateRegisters();
    populateMemoryTable(ui->tableWidget, machine);
}

void MainWindow::onLoadTriggered() {
    machine.resetRegisters();
    machine.resetMemory();
    executor->resetProgram();
    updateUI();
    QString filename = QFileDialog::getOpenFileName(this, tr("Open Object File"), "", tr("Object Files (*.obj)"));
    if (!filename.isEmpty()) {
        bool ok = loader.loadObj(machine, filename.toStdString());
        if (!ok) {
            QMessageBox::warning(this, tr("Error"), tr("Failed to load file"));
        }
    }
    populateMemoryTable(ui->tableWidget, machine);
    ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
    ui->tableWidget->horizontalHeader()->setDefaultSectionSize(30);
}

void MainWindow::on_readButton_clicked()
{
    bool ok;
    unsigned int addr = ui->addressLineEdit->text().toUInt(&ok);
    if (!ok) {
        QMessageBox::warning(this, "Napaka", "Neveljaven naslov!");
        return;
    }

    try {
        unsigned char val = machine.readByte(addr);
        ui->valueLabel->setText(QString::number(val));
    } catch (const std::out_of_range &e) {
        QMessageBox::warning(this, "Napaka", "Naslov je izven meje pomnilnika!");
    }
}

void MainWindow::on_runButton_clicked()
{
    emit startExecutor();
}


void MainWindow::on_stepButton_clicked()
{
    emit stepExecutor();
}

void MainWindow::on_stopButton_clicked()
{
    emit stopExecutor();
}

void MainWindow::setStatusLightRunning() {
    ui->statusLight->setStyleSheet("background-color: green; border-radius: 8px;");
}

void MainWindow::setStatusLightStopped() {
    ui->statusLight->setStyleSheet("background-color: yellow; border-radius: 8px;");
}

void MainWindow::setStatusLightEnded() {
    ui->statusLight->setStyleSheet("background-color: black; border-radius: 8px;");
}

void MainWindow::on_menuVizitka_triggered()
{
    QMessageBox::information(
        this,
        "Vizitka",
        "Aljaž Brodar\n"
        "Sistemska programska oprema\n"
        "Simulator SIC/XE\n"
        "2025\n"
        );
}

