/*
 *  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 "pythontab.h"
#include <QGridLayout>
#include "pybindings.h"
#include "pyinterpreter.h"

NEXTPNR_NAMESPACE_BEGIN

const QString PythonTab::PROMPT = ">>> ";
const QString PythonTab::MULTILINE_PROMPT = "... ";

PythonTab::PythonTab(QWidget *parent) : QWidget(parent), initialized(false)
{
    QFont f("unexistent");
    f.setStyleHint(QFont::Monospace);

    // Add text area for Python output and input line
    console = new PythonConsole();
    console->setMinimumHeight(100);
    console->setReadOnly(true);
    console->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
    console->setFont(f);

    console->setContextMenuPolicy(Qt::CustomContextMenu);
    QAction *clearAction = new QAction("Clear &buffer", this);
    clearAction->setStatusTip("Clears display buffer");
    connect(clearAction, &QAction::triggered, this, &PythonTab::clearBuffer);
    contextMenu = console->createStandardContextMenu();
    contextMenu->addSeparator();
    contextMenu->addAction(clearAction);
    connect(console, &PythonConsole::customContextMenuRequested, this, &PythonTab::showContextMenu);

    lineEdit = new LineEditor(&parseHelper);
    lineEdit->setMinimumHeight(30);
    lineEdit->setMaximumHeight(30);
    lineEdit->setFont(f);
    lineEdit->setPlaceholderText(PythonTab::PROMPT);
    connect(lineEdit, &LineEditor::textLineInserted, this, &PythonTab::editLineReturnPressed);

    QGridLayout *mainLayout = new QGridLayout();
    mainLayout->addWidget(console, 0, 0);
    mainLayout->addWidget(lineEdit, 1, 0);
    setLayout(mainLayout);

    parseHelper.subscribe(console);

    prompt = PythonTab::PROMPT;
}

PythonTab::~PythonTab()
{
    if (initialized) {
        pyinterpreter_finalize();
        deinit_python();
    }
}

void PythonTab::editLineReturnPressed(QString text)
{
    console->displayString(prompt + text + "\n");

    parseHelper.process(text.toStdString());

    if (parseHelper.buffered())
        prompt = PythonTab::MULTILINE_PROMPT;
    else
        prompt = PythonTab::PROMPT;

    lineEdit->setPlaceholderText(prompt);
}

void PythonTab::newContext(Context *ctx)
{
    if (initialized) {
        pyinterpreter_finalize();
        deinit_python();
    }
    console->clear();

    pyinterpreter_preinit();
    init_python("nextpnr");
    pyinterpreter_initialize();
    pyinterpreter_aquire();
    python_export_global("ctx", ctx);
    pyinterpreter_release();

    initialized = true;

    QString version = QString("Python %1 on %2\n").arg(Py_GetVersion(), Py_GetPlatform());
    console->displayString(version);
}

void PythonTab::showContextMenu(const QPoint &pt) { contextMenu->exec(mapToGlobal(pt)); }

void PythonTab::clearBuffer() { console->clear(); }

void PythonTab::info(std::string str) { console->displayString(str.c_str()); }

void PythonTab::execute_python(std::string filename) { console->execute_python(filename); }

NEXTPNR_NAMESPACE_END
