#include "grifoscope.h"

#include "qgscopeworkbench.h"
#include "qgrunsession.h"
#include "qgsettings.h"

#include "qgscopepython.h"

//#include "grifodisplaywidget.h"
#include "grifodisplaydevice.h"

#include "grifodebugdevice.h"

#include "qglogger.h"

#include <QMainWindow>
#include <QDockWidget>
#include <QIcon>
#include <QHostAddress>
//#include <QSettings>
#include <QTimer>

#include "qgrexrtgsocket.h"


//#include "qgpythonconsoledockwidget.h"
//#include "qggrifoantennawidget.h"
#include "grifotimerdockwidget.h"
#include "qgapplicationperformance.h"

//#include "qgpython.h"

#include "qgscopechrono.h"

#include "qgrexnetwork.h"
#include "qgrexconnectiondialog.h"
#include "qgaboutdialog.h"
#include <QMessageBox>
#include <QToolBar>
#include <QMenu>
#include <QToolButton>
#include <QAction>
#include <QSharedMemory>
#include <QCommandLineParser>
#include <QCommandLineOption>

#include "bsk_versign.h"

extern const struct bsk_versign_static_t versign_application_signature_;
extern const struct bsk_versign_extern_t versign_application_ext_signature_;

GrifoScope::GrifoScope(QObject *parent) : QObject(parent), singleInstance(0)
{
    //QgScopeWorkbench& wb=QgScopeWorkbench::instance();
    //wb.setApplicationTitle("GRIFO-E Scope");
    //wb.setClientInitilizer(initialize);

    singleInstance=new QSharedMemory("GrifoScope_SingleInstance");
    bool ok=singleInstance->create(1024);
    if (!ok)
    {
        QMessageBox::critical(0, "Grifo Scope", "Grifo Scope is already running!");
        exit(0);
    }

    initialize();

    //wb.show();
}

#include "qg1553overudp.h"
#include "minimcswidget.h"

#include <QCoreApplication>

extern QMainWindow* GrifoMcsMainWindow(QMainWindow* parent);
extern QWidget* GrifoMcsMainWidget(ads::CDockManager* dockManager, QMainWindow* parent, bool mon_only);

#define GRIFO_SCOPE_SETTINGS_FILE "grifo_scope.ini"

static GrifoDisplayDevice* grifo_dd;

static bool mcs_active;
static bool mcs_mon_only;

void GrifoScope::initialize()
{
    //QgAboutDialog dlgAbout;
    //dlgAbout.exec();

    QgRunSession& session=QgRunSession::defaultSession();

    session.setWorkDirPath("../../_scopetest"); //E:/Prj/GrifoEVO/Prototipo/REP/Projects/Tools/_scopetest");

    QStringList appArgs=QCoreApplication::arguments();

    session.parseStandardArguments(appArgs);
    session.validateOutputDirectory(QgRunSession::OutDirCreate);

    QgSettings::setOrganizationName("Leonardo");
    QgSettings::setOrganizationDomain("Leonardo.com");

    QgSettings::setApplicationName("GrifoScope");

    QgSettings gsett("wb.ini");
    QString prefnet=gsett.value("preferedNetwork", QString("127.0.0")).toString();
    qDebug()<<"prefered network:"<<prefnet;

    bool only_video=false;
    {
        QCommandLineParser parser;
        QCommandLineOption vonly("d");
        QCommandLineOption monly("m");
        parser.addOption(vonly);
        parser.addOption(monly);
        parser.process(appArgs);
        only_video=parser.isSet(vonly);
        mcs_mon_only=parser.isSet(monly);
    }

    QgRexConnectionDialog dlg(prefnet);
    dlg.exec();
    QHostAddress ha=QHostAddress::LocalHost;
    if (dlg.result()==QDialog::Accepted)
    {
        ha=QHostAddress(dlg.hostAddress());
        QgApplicationPerformance::instance().setNetworkInterfaceIndex(dlg.adapterIndex(), dlg.hostAddress());
    }
    else
    {
        QCoreApplication::quit();
    }

    gsett.setValue("preferedNetwork", ha.toString());

    QgRexNetwork().setNetworkInterface(ha);

    //static QgScopePythonAdaptor pyAdaptor;
    QgScopePython::activate();
    QgScopePython::createApplicationMainModule("gs");

    //QgPython::instance().createMainApplicationModule("GS");

    //if (true)
    //{
        //QMainWindow* mcsmw=GrifoMcsMainWindow(0);//wb.mainWindow());
        //wb.mainWindow()->setCentralWidget(mcsmw);
    //}

    QgScopeWorkbench& wb=QgScopeWorkbench::instance();


    {
        static const QString appVer=
        QString("%1-%2, %3")
            .arg(versign_application_signature_.data.vstr)
            .arg(versign_application_ext_signature_.data.buildid)
            .arg(versign_application_ext_signature_.data.date);

        static const QString myMsg=
                "<p><b>GrifoScope</b>: an advanced(?) Grifo Radar Run-time monitor</p>"
                "<p>Version:<b>"+appVer+"</b></p>";

        wb.setAboutMessage(myMsg);
    }
    if (0)
    {
        QToolBar* mtb=new QToolBar("Main Toolbar");
        mtb->setIconSize(QSize(16,16));
        QToolButton* mmenu_button=new QToolButton;
        mmenu_button->setText("Main Menu");
        mmenu_button->setIcon(QIcon(":/icons/icons/list89.png"));
        QAction* actAbout=new QAction("About...", this);
        connect(actAbout, &QAction::triggered, this,
                [this]()
                {
                    static const QString appVer=
                    QString("%1-%2, %3")
                        .arg(versign_application_signature_.data.vstr)
                        .arg(versign_application_ext_signature_.data.buildid)
                        .arg(versign_application_ext_signature_.data.date);

                    static const QString myMsg=
                            "<p><b>GrifoScope</b>: an advanced(?) Grifo Radar Run-time monitor</p>"
                            "<p>Version:<b>"+appVer+"</b></p>";
                    static QgAboutDialog dlgAbout(myMsg);
                    dlgAbout.exec();
                });
        mmenu_button->addAction(actAbout);
        mmenu_button->setContextMenuPolicy(Qt::ActionsContextMenu);
        mmenu_button->setPopupMode(QToolButton::InstantPopup);

        mtb->addWidget(mmenu_button);

        wb.mainWindow()->addToolBar(mtb);
    }
    //wb.setScriptSiteAdptor(&pyAdaptor);

    wb.setApplicationTitle("GRIFO-E Scope");

    //wb.runSession()->setWorkDirPath("E:/Prj/GrifoEVO/Prototipo/REP/Projects/Tools/_scopetest");
    //wb.runSession()->validateOutputDirectory(QgRunSession::OutDirCreate);

    bool timer_load=false;
    bool display_load=false;
    bool mcs_load=false;
    bool antenna_load=false;

    bool video_window=false;

    if (only_video)
    {
        display_load=true;
        mcs_active=false;
    }
    else
    {
        QSettings settings(GRIFO_SCOPE_SETTINGS_FILE, QSettings::IniFormat);

        QStringList groups=settings.childGroups();

        if (!groups.contains("Devices"))
        {
            settings.beginGroup("Devices");
            settings.setValue("timer", true);
            settings.setValue("display", true);
            settings.setValue("mcs", true);
            settings.setValue("antenna", true);
            settings.endGroup();
        }

        {
            settings.beginGroup("Devices");
            timer_load=settings.value("timer", timer_load).toBool();
            display_load=settings.value("display", display_load).toBool();
            mcs_load=settings.value("mcs", mcs_load).toBool();
            antenna_load=settings.value("antenna", antenna_load).toBool();
            video_window=settings.value("videoWindow", video_window).toBool();
            settings.endGroup();
            mcs_active=mcs_load;
        }            
    }

    //QMainWindow* mw=wb.mainWindow();
    if (mcs_load)
    {
        //LV se abilito MCS l'applicazione si blocca
        //QMainWindow* mcsmw=GrifoMcsMainWindow(wb.mainWindow());
        //wb.mainWindow()->setCentralWidget(mcsmw);
    }

    {
        GrifoDebugDevice& d=GrifoDebugDevice::instance();
        wb.mainWindow()->addToolBar(d.toolBar());
        wb.addDevice(&d); //->scopeDevice());
    }


    if (display_load)
    {
        auto gd=new GrifoDisplayDevice(video_window); //GrifoDisplayWidget;

        if (!video_window)
        {
            //auto dw=gd->displayWidget();
            /*auto dw=*/wb.addOuterPannel(Qt::RightDockWidgetArea, gd->displayWidget());
            //dw->setWindowTitle("Grifo Display");
        }

        wb.addDevice(gd); //->scopeDevice());

        grifo_dd=gd;
    }
    if (timer_load)
    {
        auto tw=new GrifoTimerDockWidget;
        wb.addOuterPannel(Qt::RightDockWidgetArea, tw);
        wb.addDevice(tw->scopeDevice());
        //wb.setProperty("timer", QVariant::fromValue(static_cast<QObject*>(gd)));
    }
#if 0
    //LV non ci sono gli include con la definizione di questo widget
    if (antenna_load)
    {
        auto aw=new QgGrifoAntennaWidget;
        wb.addOuterPannel(Qt::RightDockWidgetArea, aw);
        wb.addDevice(aw->scopeDevice());
        wb.setProperty("antenna", QVariant::fromValue(static_cast<QObject*>(aw)));
    }
#endif
    QTimer::singleShot(0, this, SLOT(postInit()));

    //wb.show();

}


extern QObject* AdsDataManagerInstance();

void GrifoScope::postInit()
{
    QgScopeWorkbench& wb=QgScopeWorkbench::instance();

    wb.show();

    if (mcs_active)
    {
        //QgScopeWorkbench& wb=QgScopeWorkbench::instance();

        //QMainWindow* mcsmw=GrifoMcsMainWindow(0);//wb.mainWindow());        
        QWidget* mcsmw=GrifoMcsMainWidget(wb.dockManager(), wb.mainWindow(), mcs_mon_only);

        wb.connect(mcsmw, SIGNAL(adsDockCreated(ads::CDockWidget*, const QString&)), &wb, SLOT(onAdsDockCreated(ads::CDockWidget*, const QString&)));
        wb.connect(mcsmw, SIGNAL(appMenuCreated(QMenu*)), &wb, SLOT(onAppMenuCreated(QMenu*)));

        wb.connect(mcsmw, SIGNAL(appReady()), &wb, SLOT(onAppReady()));

        //wb.mainWindow()->setCentralWidget(mcsmw);
        //mcsmw->show();
        if (grifo_dd!=0)
        {
            connect(grifo_dd->displayWidget(), SIGNAL(rdrCursorEvent(int, int, unsigned int)), mcsmw, SLOT(cursorGoto(int, int, unsigned int)));

        }

        QgScopePython::pythonScriptAdaptor()->registerObject("mcs", mcsmw);
        QgScopePython::pythonScriptAdaptor()->registerObject("ads", AdsDataManagerInstance());

    }
    postInit2();

    QTimer::singleShot(10, this, SLOT(postInit2()));

    //wb.restoreLayout();

    //QTimer::singleShot(10, this, SLOT(postInit2()));

}

void GrifoScope::postInit2()
{
    QgScopeWorkbench& wb=QgScopeWorkbench::instance();
    //Wait for app ready?
    wb.restoreLayout();

#if 0
    QgScopeWorkbench& wb=QgScopeWorkbench::instance();

    //QMainWindow* mcsmw=GrifoMcsMainWindow(0);//wb.mainWindow());
    QWidget* mcsmw=GrifoMcsMainWidget(wb.dockManager(), wb.mainWindow());

    //wb.mainWindow()->setCentralWidget(mcsmw);
    //mcsmw->show();
    if (grifo_dd!=0)
    {
        connect(grifo_dd->displayWidget(), SIGNAL(rdrCursorEvent(int, int, unsigned int)), mcsmw, SLOT(cursorGoto(int, int, unsigned int)));
    }
#endif
}
