/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  Miodrag Milanovic <miodrag@symbioticeda.com>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "mainwindow.h"
#include <fstream>
#include "bitstream.h"
#include "log.h"

#include <QFileDialog>
#include <QInputDialog>
#include <QLineEdit>

static void initMainResource() { Q_INIT_RESOURCE(nextpnr); }

NEXTPNR_NAMESPACE_BEGIN

MainWindow::MainWindow(std::unique_ptr<Context> context, CommandHandler *handler, QWidget *parent)
        : BaseMainWindow(std::move(context), handler, parent)
{
    initMainResource();

    std::string title = "nextpnr-ecp5 - [EMPTY]";
    setWindowTitle(title.c_str());

    connect(this, &BaseMainWindow::contextChanged, this, &MainWindow::newContext);

    createMenu();
}

MainWindow::~MainWindow() {}

void MainWindow::newContext(Context *ctx)
{
    std::string title = "nextpnr-ecp5 - " + ctx->getChipName() + " ( " + ctx->archArgs().package + " )";
    setWindowTitle(title.c_str());
}

void MainWindow::createMenu()
{
    // Add arch specific actions
    actionLoadLPF = new QAction("Open LPF", this);
    actionLoadLPF->setIcon(QIcon(":/icons/resources/open_lpf.png"));
    actionLoadLPF->setStatusTip("Open LPF file");
    actionLoadLPF->setEnabled(false);
    connect(actionLoadLPF, &QAction::triggered, this, &MainWindow::open_lpf);

    actionSaveConfig = new QAction("Save Bitstream", this);
    actionSaveConfig->setIcon(QIcon(":/icons/resources/save_config.png"));
    actionSaveConfig->setStatusTip("Save Bitstream config file");
    actionSaveConfig->setEnabled(false);
    connect(actionSaveConfig, &QAction::triggered, this, &MainWindow::save_config);

    // Add actions in menus
    mainActionBar->addSeparator();
    mainActionBar->addAction(actionLoadLPF);
    mainActionBar->addAction(actionSaveConfig);

    menuDesign->addSeparator();
    menuDesign->addAction(actionLoadLPF);
    menuDesign->addAction(actionSaveConfig);
}

static const ChipInfoPOD *get_chip_info(const RelPtr<ChipInfoPOD> *ptr) { return ptr->get(); }

static QStringList getSupportedPackages(ArchArgs::ArchArgsTypes chip)
{
    QStringList packages;
    const ChipInfoPOD *chip_info;
    if (chip == ArchArgs::LFE5U_25F || chip == ArchArgs::LFE5UM_25F || chip == ArchArgs::LFE5UM5G_25F) {
        chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_25k));
    } else if (chip == ArchArgs::LFE5U_45F || chip == ArchArgs::LFE5UM_45F || chip == ArchArgs::LFE5UM5G_45F) {
        chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_45k));
    } else if (chip == ArchArgs::LFE5U_85F || chip == ArchArgs::LFE5UM_85F || chip == ArchArgs::LFE5UM5G_85F) {
        chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_85k));
    } else {
        log_error("Unsupported ECP5 chip type.\n");
    }

    for (int i = 0; i < chip_info->num_packages; i++) {
        packages << chip_info->package_info[i].name.get();
    }
    return packages;
}

void MainWindow::new_proj()
{
    QMap<QString, int> arch;
    arch.insert("Lattice ECP5 LFE5U-25F", ArchArgs::LFE5U_25F);
    arch.insert("Lattice ECP5 LFE5U-45F", ArchArgs::LFE5U_45F);
    arch.insert("Lattice ECP5 LFE5U-85F", ArchArgs::LFE5U_85F);
    arch.insert("Lattice ECP5 LFE5UM-25F", ArchArgs::LFE5UM_25F);
    arch.insert("Lattice ECP5 LFE5UM-45F", ArchArgs::LFE5UM_45F);
    arch.insert("Lattice ECP5 LFE5UM-85F", ArchArgs::LFE5UM_85F);
    arch.insert("Lattice ECP5 LFE5UM5G-25F", ArchArgs::LFE5UM5G_25F);
    arch.insert("Lattice ECP5 LFE5UM5G-45F", ArchArgs::LFE5UM5G_45F);
    arch.insert("Lattice ECP5 LFE5UM5G-85F", ArchArgs::LFE5UM5G_85F);
    bool ok;
    QString item = QInputDialog::getItem(this, "Select new context", "Chip:", arch.keys(), 0, false, &ok);
    if (ok && !item.isEmpty()) {
        ArchArgs chipArgs;
        chipArgs.type = (ArchArgs::ArchArgsTypes)arch.value(item);

        QString package = QInputDialog::getItem(this, "Select package", "Package:", getSupportedPackages(chipArgs.type),
                                                0, false, &ok);

        if (ok && !item.isEmpty()) {
            currentProj = "";
            disableActions();
            chipArgs.package = package.toStdString().c_str();
            ctx = std::unique_ptr<Context>(new Context(chipArgs));
            actionLoadJSON->setEnabled(true);

            Q_EMIT contextChanged(ctx.get());
        }
    }
}

void MainWindow::open_lpf()
{
    QString fileName = QFileDialog::getOpenFileName(this, QString("Open LPF"), QString(), QString("*.lpf"));
    if (!fileName.isEmpty()) {
        std::ifstream in(fileName.toStdString());
        if (ctx->applyLPF(fileName.toStdString(), in)) {
            log("Loading LPF successful.\n");
            actionPack->setEnabled(true);
            actionLoadLPF->setEnabled(false);
        } else {
            actionLoadLPF->setEnabled(true);
            log("Loading LPF failed.\n");
        }
    }
}

void MainWindow::save_config()
{
    QString fileName = QFileDialog::getSaveFileName(this, QString("Save Bitstream"), QString(), QString("*.config"));
    if (!fileName.isEmpty()) {
        std::string fn = fileName.toStdString();
        disableActions();
        write_bitstream(ctx.get(), "", fileName.toStdString());
        log("Saving Bitstream successful.\n");
    }
}

void MainWindow::onDisableActions()
{
    actionLoadLPF->setEnabled(false);
    actionSaveConfig->setEnabled(false);
}

void MainWindow::onUpdateActions()
{
    if (ctx->settings.find(ctx->id("pack")) == ctx->settings.end())
        actionLoadLPF->setEnabled(true);
    if (ctx->settings.find(ctx->id("route")) != ctx->settings.end())
        actionSaveConfig->setEnabled(true);
}

NEXTPNR_NAMESPACE_END
