#include <Graphics/Dialogs/OutputDialog.hpp>

#include <utility>
#include <Converter.hpp>
#include <registry/StringWriterRegistry.hpp>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QMessageBox>
#include <QtCore/QTextStream>

OutputDialog::OutputDialog(std::shared_ptr<abstraction::Value> p_object)
    : ui(new Ui::OutputDialog)
    , object(std::move(p_object))
{
    ui->setupUi(this);
    this->setWindowTitle("Output");

    if (auto text = Converter::toXML(this->object)) {
        ui->textEdit_xml->setText(*text);
    }
    else {
        this->hideTab(ui->tab_xml);
    }

    if (auto text = Converter::toDOT(this->object)) {
        ui->textEdit_dot->setText(*text);
    }
    else {
        this->hideTab(ui->tab_dot);
    }

    if (auto text = Converter::toString(this->object)) {
        ui->textEdit_text->setText(*text);
    }
    else {
        this->hideTab(ui->tab_text);
    }

    if (auto png = Converter::toPNG(this->object)) {
        ui->label_image->setPixmap(QPixmap::fromImage(*png));
    }
    else {
        this->hideTab(ui->tab_image);
    }
}

void OutputDialog::hideTab(QWidget* tab) {
    ui->tabWidget->setTabEnabled(ui->tabWidget->indexOf(tab), false);
}

void OutputDialog::on_saveBtn_clicked() {
    auto [filter, extension] = this->getCurrentTabFileFilter();
    QString filename(QFileDialog::getSaveFileName(this,
                                                  tr("Save file"),
                                                  QDir::homePath(),
                                                  filter));
    if (filename.isEmpty()) {
        return;
    }

    if (!filename.endsWith(extension)) {
        filename += extension;
    }

    auto type = this->getCurrentTabType();
    if (type == TabType::Image) {
        Converter::saveToImage(this->object, filename);
    }
    else {
        QFile file(filename);
        if (!file.open(QFile::WriteOnly | QFile::Text | QFile::Truncate)) {
            QMessageBox::warning(this, "Warning", "Failed to open file.");
            return;
        }

        QTextStream stream(&file);
        switch (type) {
            case TabType::Text:
                stream << ui->textEdit_text->toPlainText();
                break;
            case TabType::XML:
                stream << ui->textEdit_xml->toPlainText();
                break;
            case TabType::DOT:
                stream << ui->textEdit_dot->toPlainText();
                break;
            case TabType::Image:
                Q_ASSERT(false);
                break;
        }
        file.close();
    }
}

TabType OutputDialog::getCurrentTabType() const {
    if (ui->tabWidget->currentWidget() == ui->tab_text) {
        return TabType::Text;
    }
    else if (ui->tabWidget->currentWidget() == ui->tab_xml) {
        return TabType::XML;
    }
    else if (ui->tabWidget->currentWidget() == ui->tab_dot) {
        return TabType::DOT;
    }
    else if (ui->tabWidget->currentWidget() == ui->tab_image) {
        return TabType::Image;
    }

    throw std::logic_error ( "Invalid tab type." );
}

std::pair<QString, QString> OutputDialog::getCurrentTabFileFilter() const {
    switch (this->getCurrentTabType()) {
        case TabType::Text: return { "Text files (*.txt)", ".txt" };
        case TabType::XML: return { "XML files (*.xml)", ".xml" };
        case TabType::DOT: return { "DOT files (*.dot)", ".dot" };
        case TabType::Image: return { "PNG files (*.png)", ".png" };
    }
    throw std::logic_error ( "Invalid tab type" );
}
