#include "qggrifobeamupform.h"
#include "ui_qggrifobeamupform.h"

#include <qgnetworkinterface.h>
#include "qgpropertywidget.h"

#include <QTreeWidgetItem>
#include <QGridLayout>
#include <QCheckBox>

#include <QHostInfo>
#include <QHostAddress>
#include <QNetworkInterface>

#include <QFileDialog>
#include <QDir>
#include <QUrl>
#include <QMessageBox>

#include <QDebug>
#include <QSettings>

#include <QDropEvent>
#include <QDragEnterEvent>
#include <QMimeData>
#include <QStyle>
#include <QList>
#include <QInputDialog>

#include "qzip.h"

#include "bsk_tftp_pfs.h"

#include <QRegExp>

#include "downloadablefile.h"

#include "mydebug.h"

#include "historydbform.h"

#include "fpgabeammeupstring.h"

#include "fpgaflashxml.h"


#define TFTP_DEFAULT_PORT 50069

bool IS_TFTP_CONNECTED;

QString TMP_FOLDER;

struct fileToWrite_s
{
    bool validConfig;               // true if i read a valid config from xml file present into zip files
    QString targetFlash;            // namePrefix of valid config
    QString primaryFile;            // bin file to write on first spi port (primary)
    QString primaryMD5;             // md5 for primary file
    bool primaryDone;               // true if write is done
    QString secondaryFile;          // bin file to write on second spi port (secondary)
    QString secondaryMD5;           // md5 for secondary file
    bool secondaryDone;             //true if write is done
};

static fileToWrite_s fileToWrite;

void resetFileToWrite()
{
    fileToWrite.validConfig = false;
    fileToWrite.targetFlash = "";
    fileToWrite.primaryDone = false;
    fileToWrite.primaryFile = "";
    fileToWrite.primaryMD5 = "";
    fileToWrite.secondaryDone = false;
    fileToWrite.secondaryFile = "";
    fileToWrite.secondaryMD5 = "";
}


enum fpga_t
{
    fpga_no_specific = 0,
    fpga_carrier1_fpga1 = 1,
    fpga_carrier1_fpga2 = 2,
    fpga_carrier2_fpga1 = 3,
    fpga_carrier2_fpga2 = 4,
    fpga_digital_ctrl = 5
};

//QString ShowFileInfo(const QString& fname, bool popup=true);

static QString probeNetworks(const QString& prefered_net, QComboBox* cb)
{
    unsigned int prefered_index=0;
    static bool privateSubnet=false;
    static QString preferedNetwork("127.0.0.1");

    if (!prefered_net.isEmpty())
        preferedNetwork=prefered_net;

    QHostInfo hi=QHostInfo::fromName(QHostInfo::localHostName());
    //ui->groupBox->setTitle(QString("Host: %1").arg(hi.hostName()));
    QList<QNetworkInterface> hal=QNetworkInterface::allInterfaces();
    if (hal.isEmpty())
    {
        MyDebug.logMsg(type_log_error,
                         origin_msg_generic,
                         "Network Config: NO HOST ADDRESSES");
        cb->addItem("<No Interface>");
        cb->setEnabled(false);
    }
    else
    {
        foreach(QNetworkInterface nif, hal)
        {
            //QList<QHostAddress> nhal=nif.allAddresses();
            QList<QNetworkAddressEntry> nhal=nif.addressEntries();
            foreach(QNetworkAddressEntry aentry, nhal)
            {
                bool private_subnet=false;

                QHostAddress a=aentry.ip();

                if (!(a.toString().startsWith("192.168") ||
                      a.toString().startsWith("169.254") ||
                      a.toString().startsWith("127.")))
                    continue;

                cb->addItem(QString("%1 (%2) [%3]").arg(nif.humanReadableName()).arg(a.toString()).arg(nif.index()), a.toString());
                int currentIndex=cb->count()-1;
                //if (a.toString().startsWith("192.168.0") ||a.toString().startsWith("192.168.2"))
                if (a.toString().startsWith(preferedNetwork))
                {
                    prefered_index=currentIndex;
                    private_subnet=true;
                    privateSubnet=privateSubnet;
                }
                cb->setItemData(currentIndex, private_subnet, Qt::UserRole+1);
                cb->setItemData(currentIndex, nif.index(), Qt::UserRole+2);

                //ui->comboBoxInterface->seIif (nif.flags() & QNetworkInterface::IsUp)
            }
        }
        if (prefered_index)
            cb->setCurrentIndex(prefered_index);
    }
    return hi.hostName();
}

#define MAX_TARGETS 64

struct targets_t
{
    unsigned int valid;
    QgGrifoDownloadSite sites[MAX_TARGETS];
};

static targets_t targets;

struct PgmSteps
{
    QLabel* lbl;
    QCheckBox* chk;
};
static PgmSteps pgmSteps[10];

QgGrifoBeamUpForm::QgGrifoBeamUpForm(QWidget *parent) :
    QWidget(parent),
    props(QgGrifoBeamupProperties::instance()),
    ui(new Ui::QgGrifoBeamUpForm),
    settings("./grifo_beamup.ini", QSettings::IniFormat)
{
    IS_TFTP_CONNECTED = false;

    fileToWrite.validConfig = false;

    QStyle* st=QApplication::style();

    ui->setupUi(this);

    ui->tbRefresh->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);

    ui->tbRefresh->setIcon(st->standardIcon(QStyle::SP_DriveNetIcon)
                );
    ui->tbRefresh->setText("Connect");

    ui->tbFileSelect->setIcon(st->standardIcon(QStyle::SP_FileIcon)
    );

    ui->tbGo->setIcon(st->standardIcon(QStyle::SP_ArrowUp)
                      );

    ui->tbDropSelect->setIcon(st->standardIcon(QStyle::SP_FileDialogNewFolder)
                                  );

    ui->tbSettings->setIcon(st->standardIcon(QStyle::SP_FileDialogListView)
                                );

    ui->tbFileInfo->setIcon(st->standardIcon(QStyle::SP_FileDialogInfoView));

    ui->tbHistory->setIcon(st->standardIcon(QStyle::SP_DirHomeIcon)
                                  );

    entitiesForm=new QgGrifoDownloadEntitiesForm;

    int ipos=ui->verticalLayout->indexOf(ui->placeholder);
    ui->verticalLayout->insertWidget(ipos, entitiesForm);
    ui->placeholder->setVisible(false);

    ui->leMsg->setMaximumBlockCount(5000);

    entitiesForm->setVisible(false);

    {
        QHostInfo hi=QHostInfo::fromName(QHostInfo::localHostName());
        QString host=QString("Host: %1").arg(hi.hostName());

        ui->hostName->setText(host);
    }

    ui->progressBar->setValue(0);
    ui->progressBar->setEnabled(false);
    ui->progressBar->setTextVisible(false);
    //setState(1);

    fileSelector.setObjectName("GrifoBeamUpFileSelector");
    fileSelector.setOption(QFileDialog::ReadOnly, true);

    fileSelector.setViewMode(QFileDialog::Detail);
    fileSelector.setNameFilters(
                QStringList()<<"archive (*.zip)"<<"Binary (*.bin)"<<"ELF (*.elf *.out)"<<"Any files (*)");

    connect(ui->tbFileSelect, &QToolButton::clicked, this,
            [this](bool)
    {
        QString tmp=fileSelector.directory().absolutePath();
        fileSelector.setOption(QFileDialog::ReadOnly, true);
        fileSelector.setFileMode(QFileDialog::AnyFile);
        fileSelector.setDirectory(tmp);

        if (fileSelector.exec())
        {
            ui->leFile->setText(fileSelector.selectedFiles().at(0));
            //stateReady();
            selectByFile(fileSelector.selectedFiles().at(0));
        }
    }
            );
    connect(ui->tbDropSelect, &QToolButton::clicked, this,
            [this](bool)
    {
        fileSelector.setFileMode(QFileDialog::Directory);
        if (fileSelector.exec())
        {
            selectWatchDir(fileSelector.selectedFiles().at(0));
        }
    });

    connect(&fileWatcher, &QFileSystemWatcher::directoryChanged, this, &QgGrifoBeamUpForm::updateWatchedDirectory);
    connect(&fileWatcher, &QFileSystemWatcher::fileChanged, this, &QgGrifoBeamUpForm::updateWatchedFile);

    connect(ui->tbGo, &QToolButton::clicked, this, &QgGrifoBeamUpForm::uploadGo);
#if 0
    connect(&tftp, &QgGrifoBeamUpTftp::progressInfo, this,
            [this](int n, const QString& msg)
    {
        if (n==-1)
            ui->progressBar->setRange(0, 0);
        else
        {
            ui->progressBar->setRange(0, 100);
            ui->progressBar->setValue(n);
        }
        ui->progressLabel->setText(msg);
    });
    connect(&tftp, &QgGrifoBeamUpTftp::sendTerminated, this,
            [this]()
    {
        ui->progressBar->setRange(0, 100);
        ui->progressBar->setValue(100);
        showMessage("Completed"); //ui->progressLabel->setText("Completed");
        stateReady();
    });

    connect(&tftp, &QgGrifoBeamUpTftp::transferError, this,
            [this](int code, const QString& msg)
    {
        showMessage(QString("%1 (%2)").arg(msg).arg(code)); //ui->progressLabel->setText(QString("%1 (%2)").arg(msg).arg(code));
        ui->progressBar->reset();
        ui->progressBar->setRange(0, 100);
        ui->progressBar->setValue(0);
        ui->progressBar->setEnabled(false);
        QMessageBox::critical(this, QString(), QString("Transfer Error: %1 (%2)").arg(msg).arg(code));
        stateReady();        
    });

    connect(&tftp, &QgGrifoBeamUpTftp::serverHello, this,
            [this](unsigned int ip, int port, const QString& msg)
    {
        ui->leMsg->appendPlainText(msg); //setText(msg);
        serverHello(ip, port, msg);
    });
#endif

    //general configuration of app
    {
        QSettings& s=settings;//("./grifo_beamup.ini", QSettings::IniFormat);
        s.beginGroup("GrifoBeamUp");
        QString prefnet=s.value("preferedNetwork", QString("$127.0.0")).toString();
        if (prefnet.startsWith('$'))
            prefnet=prefnet.remove('$');

        probeNetworks(prefnet, ui->cbNetwork);

        QgNetworkInterface::setNetworkIP(prefnet);

        ui->leFile->setText(s.value("file", QString()).toString());
        fileSelector.restoreState(s.value("fileselector").toByteArray());
        s.endGroup();
    }


#if 0
    tftp.bind(QHostAddress(QgNetworkInterface::networkIP()));

    ui->tbNetwork->setText(netDlg->hostNetworkName());
    QgNetworkInterface::setNetworkIP(netDlg->hostAddress());

    connect(ui->tbNetwork, &QToolButton::clicked, this,
            [this](bool)
    {
        netDlg->exec();
        if (netDlg->result()==QDialog::Accepted)
        {
            QgNetworkInterface::setNetworkInterface(QHostAddress(netDlg->hostAddress()));
            ui->tbNetwork->setText(netDlg->hostNetworkName()); //QgNetworkInterface::networkIP());
        }
    });
#endif

    connect(ui->tbRefresh, &QToolButton::clicked, this,
            [this](bool)
    {
        refreshServers();
    });

    connect(ui->tbSettings, &QToolButton::clicked, this,
            [this](bool)
    {
        static QgPropertyDialog dlg(&props, this);
        dlg.show();

    });

    props.restoreSettings(settings);

    if (!props.property("lastDirectory").toString().isEmpty())
        fileSelector.setDirectory(props.property("lastDirectory").toString());

    pingTimer.setSingleShot(true);
    pingTimer.setInterval(2000);
    connect(&pingTimer, &QTimer::timeout, this,
            [this]()
    {
       ui->tbRefresh->setEnabled(true);
    });

    ui->cbTarget->setDuplicatesEnabled(false);
    ui->cbPartition->setDuplicatesEnabled(false);

    ui->cbTarget->addItem(QgNetworkInterface::networkIP()+":"+QString("%1").arg(props.property("tftpFirstPort").toInt()));

    connect(entitiesForm, &QgGrifoDownloadEntitiesForm::itemSelected, this,
            [this](void*xs, void*xp)
    {
            bsk_download_site_t* s=(bsk_download_site_t*)xs;
            bsk_download_partition_t* p=(bsk_download_partition_t*)xp;
            updateSelected(s, p);
    });

    stateReady();

    /*
     * Configuration target from file
    */

    flashTargets = flashTargetClass::instance();

    if (flashTargets->readTargets())
    {
        //QStringList list = flashTargets->getInfoLists();
        //ui->cbTgt->addItems(list);
        setTargetOnScreen();

        default_ip = flashTargets->getDefIp();
    }
    else
    {
        qDebug()<<"Error read targets file config!";
    }

    //readConfigFile();

    programmer=new FgpaProgrammer;

    connect(ui->leFile, &QLineEdit::editingFinished, this,
            [this]()
    {
        selectByFile(ui->leFile->text());
    });

    selectWatchDir(props.property("watchedDirectory").toString());

    setAcceptDrops(true);

    ui->groupBox->setEnabled(false);

    connect(entitiesForm, &QgGrifoDownloadEntitiesForm::fileDroppped, this, [this](QTreeWidgetItem* i, const QString& name)
    {
        selectByFile(name, i);
    });

    {
        QGridLayout* g=ui->gridLayout_2;
        for(int i=0; i<7; ++i)
        {
            pgmSteps[i].chk=new QCheckBox;
            if (i<1)
                pgmSteps[i].chk->setChecked(false);
            else
                pgmSteps[i].chk->setChecked(true);

            pgmSteps[i].lbl=new QLabel("...");
            g->addWidget(pgmSteps[i].chk, i+1, 0);
            g->addWidget(pgmSteps[i].lbl, i+1, 2);
        }
    }

    connect(programmer, &FgpaProgrammer::statusChanged, this, &QgGrifoBeamUpForm::statusUpdated, Qt::QueuedConnection);

    programmer->setSimulate(ui->cbSimulate->isChecked());
    programmer->setSRIOMemory(ui->cb_TargetAddress->isChecked());

    _dbHistory = dbHistory::instance();

    QHostInfo hi=QHostInfo::fromName(QHostInfo::localHostName());
    _dbHistory->setParam(hi.hostName());
    _dbHistory->refreshList();

    ui->groupBox_3->hide();
    ui->groupBox_2->hide();
    ui->label_2->hide();
    ui->leDir->hide();
    ui->tbDropSelect->hide();

    ui->tbGo->hide();
    ui->cbPartition->hide();
    ui->cbTarget->hide();

    ui->lbServer->hide();

    statusBar = new QStatusBar(this);
    ui->verticalLayout->addWidget(statusBar);
    statusBar->showMessage("Ready", 3000);

    ui->leMsg->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);

    ui->tabWidget->setCurrentIndex(1);

    ui->btnWrite->setStyleSheet("QPushButton { background-color: green; color:white; }\n"
                                "QPushButton:enabled { background-color: rgb(0,200,0); color:white; }\n");

    TMP_FOLDER = QApplication::applicationDirPath() + "/tmp";
}

QgGrifoBeamUpForm::~QgGrifoBeamUpForm()
{
    delete ui;
}

void QgGrifoBeamUpForm::updateSelected(const bsk_download_site_t* site,const bsk_download_partition_t* p)
{
    if (!site)
        return;

    MyDebug.logMsg(type_log_info,
                     origin_msg_generic,
                     QString("select: %1 %2").arg(site->name).arg(p->name));

    ShowTargetInfo(true);
}

#include <QProgressBar>

void QgGrifoBeamUpForm::selectByFile(const QString& fname, QTreeWidgetItem*)
{
    /*
     * in base al file selezionato devo capire queste cose
     *
     * le flash da programmare sono EIF 1 con 2 flash da 128 mega 0x73, EIF 2 con altre due flash da 128 mega ????
     *                              DFE 1 con 2 flash da 256 mega 0x16, DFE 2 con altre due flash da 256 mega ????
     * Quindi in totale sono 8 flash da programmare.
     *
     * 1 se si tratta di un file binario devo chiedere su quale flash devo programmarlo in maniera selettiva tra le 8 disponibili, in quanto
     * deve essere salvato su di una flash sola tra quelle disponibili, quindi occorre chiedere su quale scheda e se primaria o secondaria
     *
     * 2 se si tratta di un file zip, occorre verificare che si tratti di un file zip valido, con dentro i due file binari corretti, devi chiedere
     * su quale scheda devo andare senza chiedere primaria/secondaria in quanto che ne sono due da caricare.
     * DA FARE - Potrei chiedere se devo caricare entrambe le flash oppure sono una delle due
     *
     *
     * IMPORTANTE:
     * nell'history, inserire un bottone che mi permetta di recuperare una vecchia installazione per riprocessarla.
     * Per semplificare la fase di recupero dovrei poter selezionare se rifare la programmazione su entrambe le flash, oppure solo su primaria/secondaria.
     * */

    QFileInfo finfo(fname);
    QString n=finfo.fileName();

    resetFileToWrite();

    if (finfo.completeSuffix()=="zip")
    {
        // file zip with 2 binary file and xml info file.
        MyDebug.logMsg(type_log_info,
                         origin_msg_generic,
                         "file zip with info");

        if (!extractInfoFromZip(fname))
        {
            MyDebug.logMsg(type_log_error,
                             origin_msg_generic,
                             "Config present into zip file is not valid!");
        }

        MyDebug.logMsg(type_log_info,
                         origin_msg_generic,
                         QString("target fpga-flash : %1").arg(fileToWrite.targetFlash));

        entitiesForm->setUnCheckedAll();

        //for every targets read from configuration files
        for (int i = 0; i<flashTargets->countTarget(); i++)
        {
            targetItem tgt = flashTargets->getTarget(i);
            if (tgt.filePrefix==fileToWrite.targetFlash)
            {
                entitiesForm->setChecked(tgt.name);
            }
         }
    }
    else
    if (finfo.completeSuffix()=="bin")
    {
        // file binary, without info
        MyDebug.logMsg(type_log_info,
                         origin_msg_generic,
                         "file binary without info");

    }
}

//*************************************************
//  connect to server selected from combobox
//*************************************************
void QgGrifoBeamUpForm::refreshServers()
{
    if (ui->cbNetwork->count()<1)
        return;

    if (ui->cbNetwork->isEnabled())
    {
        QString ip=ui->cbNetwork->itemData(ui->cbNetwork->currentIndex()).toString();

        bool match=ip.startsWith("127.0.", Qt::CaseInsensitive);

        QString msg = "";

        if (match)
        {
            tftp.bindRemote(QHostAddress("127.0.0.1"), TFTP_DEFAULT_PORT);
            //ui->cbTarget->setCurrentText(QString("%1:%2").arg("127.0.0.1").arg(TFTP_DEFAULT_PORT));
            ui->lbServer->setText(QString("TFTP server: %1:%2").arg("127.0.0.1").arg(TFTP_DEFAULT_PORT));
            msg = QString("Connected to TFTP server at %1:%2").arg("127.0.0.1").arg(TFTP_DEFAULT_PORT);
        }
        else
        {
            tftp.bindRemote(QHostAddress(default_ip), TFTP_DEFAULT_PORT);
            tftp.fixServerBug((default_ip==DSP_ETHERNET_IP) ? 2 : 0);
            //ui->cbTarget->setCurrentText(QString("%1:%2").arg(default_ip).arg(TFTP_DEFAULT_PORT));
            ui->lbServer->setText(QString("TFTP server: %1:%2").arg(default_ip).arg(TFTP_DEFAULT_PORT));
            msg = QString("Connected to TFTP server at %1:%2").arg(default_ip).arg(TFTP_DEFAULT_PORT);
        }

        QgNetworkInterface::setNetworkInterface(QHostAddress(ip));

        QgNetworkInterface::setNetworkIP(ip);
        MyDebug.logMsg(type_log_info,
                         origin_msg_tftp,
                         QString("%1").arg(QgNetworkInterface::networkIP()));
        tftp.bind(QHostAddress(QgNetworkInterface::networkIP()));

        IS_TFTP_CONNECTED = true;

        ui->cbNetwork->setEnabled(false);
        //ui->groupBox->setEnabled(true);

        ui->lbServer->show();

        addToLog(msg);

        statusBar->showMessage(msg);
    }

    ui->tbRefresh->setEnabled(false);

    programmer->setTftp(&tftp);
    programmer->setHistory(_dbHistory);
}

void QgGrifoBeamUpForm::serverHello(unsigned int /*ip*/, int /*port*/, const QString &/*msg*/)
{
#if 0
    QgGrifoDownloadSite* s=&targets.sites[targets.valid];

    memset(&s->site, 0, sizeof s->site);
    bsk_download_site_t* site=&s->site;

    int r=bsk_tftp_mfs_decode_site(site, msg.toLatin1().constData());

    site->media_address=ip;
    site->media_port=port;
    s->tgt=0;

    if (r==0)
    {
        TgtMatch* tgt=tgtMatchSet.lookupCSCI(site->name, site->address);
        if (tgt)
            s->tgt=tgt; //appName=tgt->appName;

        entitiesForm->addSite(s);
        QHostAddress ha(site->media_address);
        QString n=QString("%1:%2/%3").arg(ha.toString()).arg(site->media_port).arg(site->name);
        ui->cbTarget->addItem(n, (quint64)site);

        ++targets.valid;

        for(int i=0; i<bsk_download_site_t::k_max_partitions; ++i)
        {
            if (site->partitions[i].name[0]==0)
                break;

            QString queryStr=QString("$PGM:%1/$version$").arg(site->partitions[i].name);
            tftp.queryVersion(ip, port, queryStr);
        }
        pingTimer.start();
    }
    entitiesForm->setVisible(true);
#endif
}

void QgGrifoBeamUpForm::partitionUpdate(unsigned int /*ip*/, int /*port*/, const QString& /*msg*/)
{
}

void QgGrifoBeamUpForm::saveSettings()
{
    {
        QSettings& s=settings; //("./grifo_beamup.ini", QSettings::IniFormat);
        s.beginGroup("GrifoBeamUp");
        s.setValue("preferedNetwork", QString('$')+QgNetworkInterface::networkIP());
        s.setValue("file", ui->leFile->text());
        s.setValue("fileselector", fileSelector.saveState());
        props.setProperty("lastDirectory", fileSelector.directory().absolutePath());
        s.setValue("dirHistory", fileSelector.history());
        s.endGroup();

        props.saveSettings(settings);
    }
}

void QgGrifoBeamUpForm::updateWatchedDirectory(const QString& path)
{
    QDir dir(path);
    QStringList currentList=dir.entryList();
    QStringList changed;

    foreach(QString s, currentList)
    {
        bool hit=watchedFiles.contains(s);
        if (!hit)
            changed.append(s);
    }

    watchedFiles=currentList;

    MyDebug.logMsg(type_log_info,
                     origin_msg_generic,
                     QString("Directory update: %1 %2").arg(path).arg(changed.count()));

    if (changed.size()>0)
    {
        for(int i=0; i<changed.size(); ++i)
        {
            addPendingList(dir.absoluteFilePath(changed.at(0)));
            //ui->leFile->setText(dir.absoluteFilePath(changed.at(0)));
        }
    }
}

void QgGrifoBeamUpForm::updateWatchedFile(const QString& path)
{
    MyDebug.logMsg(type_log_info,
                     origin_msg_generic,
                     QString("File update: %1").arg(path));

}

void QgGrifoBeamUpForm::setState(int s)
{
    state=s;
    bool enable=false;
    if (state==0)
    {
        enable=true;
        //ui->cbNetowrkSelection->setEnabled(false);
        ui->tbGo->setText("Upload...");
    }
    else
        ui->tbGo->setText("Break...");

    //ui->tbNetwork->setEnabled(enable);
    ui->tbRefresh->setEnabled(enable);
    //ui->tbGo->setEnabled(enable);
    ui->tbFileSelect->setEnabled(enable);
    ui->tbDropSelect->setEnabled(enable);
    ui->leFile->setEnabled(enable);
    //ui->leDir->setEnabled(enable);
    ui->cbPartition->setEnabled(enable);
    ui->cbTarget->setEnabled(enable);

    entitiesForm->setEnabled(enable);

    if (enable)
    {
        if (ui->progressBar->minimum()==ui->progressBar->maximum())
        {
            ui->progressBar->setRange(0, 100);
            ui->progressBar->setValue(0);
            ui->progressBar->setEnabled(false);
        }
    }
    ui->groupBox->setEnabled(enable);
}

void QgGrifoBeamUpForm::stateReady()
{
    setState(0);
    if (pendingList.count())
    {
        QString tmp=pendingList.at(0);
        pendingList.pop_front();
        if (tmp.isEmpty())
        {
            return;
        }
        ui->leFile->setText(tmp);
        selectByFile(tmp);
        uploadGo();
    }
}

void QgGrifoBeamUpForm::stateBusy()
{
    setState(1);
}


void QgGrifoBeamUpForm::uploadGo()
{
    /*if (state!=0)
    {
        QMessageBox::question(this, QString(), QString("Break operation?"));
        return;
    }
    int n=ui->cbTarget->currentIndex();

    //controlla se è stato selezionato un indirizzo target valido
    if (n<0)
    {
        ui->progressLabel->setText("Target not selected");
        ui->leMsg->appendPlainText(QString("Target not selected"));
        QMessageBox::critical(this, QString(), QString("Target not selected"));
        return;
    }

    //controlla se il file da spedire è leggibile
    QFileInfo finfo(ui->leFile->text());
    if (!finfo.isReadable())
    {
        ui->leMsg->appendPlainText(QString("File not readable"));
        QMessageBox::critical(this, QString(), QString("File not readable"));
        return;
    }

    //controlla se l'indirizzo ftp del server a cui collegarci è valido
    QString tgtStr=ui->cbTarget->currentText();
    tgtStr="ftp://"+ui->cbTarget->currentText();
    QUrl url(tgtStr);
    if (!url.isValid())
    {
        QString msg=QString("Invalid URL %1").arg(tgtStr);
        ui->progressLabel->setText(msg);
        ui->leMsg->appendPlainText(msg);
        QMessageBox::critical(this, QString(), msg);
        return;
    }

    //apertura connessione con server tftp remoto
    QHostAddress ha(url.host());
    int port=url.port();
    tftp.bindRemote(ha, port);

    //ui->progressLabel->setText(tmp);
    {
        MyDebug.logMsg(type_log_info,
                         origin_msg_generic,
                         QString("Upload to %1 %2@%3:%4...").arg(tgtStr).arg("?").arg(ha.toString()).arg(port));
    }

    QString partName;
    n=ui->cbPartition->currentIndex();
    if (n>=0)
    {
        unsigned long long p=ui->cbPartition->currentData().toULongLong();
        if (p && !ui->cbPartition->currentText().isEmpty())
            partName="$PGM:"+ui->cbPartition->currentText()+"/%1";
    }

    if (partName=="")
    {
        partName ="$PGM:uploadfile/%1";
    }
    QString fnameStr=finfo.fileName();
#if 0
    {
        QZipReader zip(ui->leFile->text());
        QList<QZipReader::FileInfo> zlst=zip.fileInfoList();
        if(zlst.size())
        {
          QString tmpname=zlst.at(0).filePath;
          //standardDialog()->setFileInfo(QString("%1 (%2)").arg(tmpname).arg(params.simplifiedFileName));
          fnameStr+="("+tmpname+")";
        }
    }
#endif
    QString opmsg=QString("%1 -> %2/%3").arg(fnameStr).arg(ui->cbTarget->currentText()).arg(partName);

    showMessage(opmsg);

    int qr=QMessageBox::question(this, QString(), opmsg, QMessageBox::Yes|QMessageBox::No|QMessageBox::Abort);
    if (qr!=QMessageBox::Yes)
    {
        if (qr==QMessageBox::Abort)
            pendingList.clear();
        return;
    }

    //ui->progressLabel->setText("Upload start...");

    bool ok=tftp.sendFile(ui->leFile->text(), partName);

    //ui->tbNetwork->setEnabled(false);

    ui->lbOperation->setText(opmsg);
    if (ok)
    {
        stateBusy();
        //ui->tbGo->setEnabled(false);
        ui->progressBar->reset();
        ui->progressBar->setRange(0, 0);
        ui->progressBar->setEnabled(true);
    }*/
}

void QgGrifoBeamUpForm::dragEnterEvent(QDragEnterEvent * event)
{
    if (event->mimeData()->hasUrls())
    {
        QList<QUrl> lst=event->mimeData()->urls();
        if ((lst.size()>0) && lst.size()<10)
        {
            //if (lst.at(0).isLocalFile())
              event->acceptProposedAction();
        }
    }
}

void QgGrifoBeamUpForm::dropEvent(QDropEvent * event)
{
    QList<QUrl> lst=event->mimeData()->urls();
    if (lst.size()>0)
    {
        for(int i=0; i<lst.size(); ++i)
        {
            if (lst.at(i).isLocalFile())
            {
                //ui->leFile->setText(lst.at(0).path());
                //selectByFile(lst.at(0).path());

                addPendingList(lst.at(i).toLocalFile());
            }
        }
    }
}

void QgGrifoBeamUpForm::selectWatchDir(const QString& dName)
{
    if (dName.isEmpty())
        return;

    QDir dir(dName);
    if (!dir.isReadable())
        return;

    ui->leDir->setText(dName);
    fileWatcher.removePaths(fileWatcher.directories());
    fileWatcher.addPath(dName);
    props.setProperty("watchedDirectory", dName);
    watchedFiles.clear();
    watchedFiles=dir.entryList(QDir::Files|QDir::NoDotAndDotDot);
}

void QgGrifoBeamUpForm::addPendingList(const QString& file)
{
    pendingList.append(file);

    if (state==0)
    {
        stateReady();
        //ui->leFile->setText(lst.at(0).path());
        selectByFile(file); //lst.at(0).path());
        //uploadGo();
    }
}

void QgGrifoBeamUpForm::showMessage(const QString& msg)
{
    //ui->progressLabel->setText(msg);
    //ui->leMsg->appendPlainText(msg);
    addToLog(msg);
}

QString QgGrifoBeamUpForm::ShowFileInfo(const QString& fname, bool popup)
{
    QFileInfo finfo(fname);
    if (!finfo.exists())
    {
        QMessageBox::critical(0, "ERROR open file", "File <p/>"+fname +"<p/> is not available.");
        return "";
    }

    DownloadableFile df;
    df.open(fname);
    BinaryFileInfo bfi=df.info();
    BinaryInfo bi=bfi.binaryInfo;

    QString infoText="";

    if (finfo.completeSuffix()=="zip")
    {
        if (!extractInfoFromZip(fname))
            return "";

        infoText=
                "File: "+bfi.filename+"<p/>\n"
                +"File CRC32: "+QString("%1").arg(bfi.zip_crc32, 0, 16).toUpper()+"<p/>\n";

        infoText+=
                +"  target flash: <b>"       +fileToWrite.targetFlash            +"</b><p/>\n"
                +"  primary file: <b>"       +QFileInfo( fileToWrite.primaryFile ).fileName()  +"</b><p/>\n"
                +"  primary file MD5: <b>"   +fileToWrite.primaryMD5       +"</b><p/>\n"
                +"  primary file: <b>"       +QFileInfo( fileToWrite.secondaryFile ).fileName()     +"</b><p/>\n"
                +"  primary file MD5: <b>"   +fileToWrite.secondaryMD5     +"</b><p/>\n";

        entitiesForm->setUnCheckedAll();

        //for every targets read from configuration files
        for (int i = 0; i<flashTargets->countTarget(); i++)
        {
            targetItem tgt = flashTargets->getTarget(i);
            if (tgt.filePrefix==fileToWrite.targetFlash)
            {
                entitiesForm->setChecked(tgt.name);
            }
         }
    }
    else
    if (finfo.completeSuffix()=="bin")
    {
            infoText=
                    "File: "+bfi.filename+"<p/>\n"
                    +"&emsp;&emsp;Size: "+QString("%1").arg(bfi.uncompressed_size)+" ("+QString("%1").arg(bfi.compressed_size)+")<p/>\n"
                    +"&emsp;&emsp;Container hash: "+bfi.file_md5+"<p/><p/>\n"
                    +"File CRC32: "+QString("%1").arg(bfi.zip_crc32, 0, 16).toUpper()+"<p/>\n";

            infoText+=
                    "  Name: <b>"+bi.m_name+"</b><p/>\n"
                    +"  Version: <b>"+bi.m_version+" "+bi.m_bid+"</b><p/>\n"
                    +"  Date: <b>"+bi.m_date+"</b><p/>\n"
                    +"  IBC: "+bi.m_ibc+"<p/>\n"
                    +"  P/N: "+bi.m_pn+"<p/>\n"
                    +"  Part Type: "+bi.m_partType+"<p/>\n"
                    +"  Architecture: "+bi.m_pn+" - "+bi.m_archName+"<p/>\n"
                    +"  Format: "+bi.m_fmtName+"<p/>\n"
                    +"  Generator: "+bi.m_generator+"<p/>\n"
                    //+"  Version: "+bi.m_bid+"<p/>\n"
                    +"  Info: "+bi.m_usr+"<p/>\n"
                    +"  Host: "+bi.m_host+"<p/>\n"
                    +"  Signature: "+bi.m_md5+"<p/>\n";

            fileToWrite.validConfig = false;
    }


    if (popup)
        QMessageBox::information(0, "File: "+bfi.sourcefile, infoText);
    return infoText;
}

void QgGrifoBeamUpForm::on_tbFileInfo_clicked()
{
    ShowFileInfo(ui->leFile->text());
}

void QgGrifoBeamUpForm::programWithProfile(bool checked)
{
    /*QString address = QString("0x%1-0x%2").arg(profile.user_address_start_area, 0, 16).arg(profile.user_address_stop_area, 0, 16);
    QString srio = QString("%1@%2:%3").arg(profile.slotAddress).arg(profile.ip).arg(profile.port);
    int spi = int(profile.spiport);

    _dbHistory->addNewFile(profile.FileToSend,
                           db_error_no_error,
                           profile.fName,
                           db_status_started,
                           address,
                           srio,
                           spi);*/

    if (ui->cbSimulate->checkState()==Qt::Checked)
    {
        //è simulazione con dati di test
        if (checked)
            programmer->start(1, ui->sbSectorSize->value(), ui->sbBase->value());
        else
            programmer->start(0, ui->sbSectorSize->value(), ui->sbBase->value());
    }
    else
    {
        //non è simulazione
        programmer->start(profile);
    }
}

void QgGrifoBeamUpForm::
on_btnStart_clicked(bool checked)
{
    //indivisuare il profilo da usare per le operazione di programmazione
    if (!getProfile(ui->sbSectorSize->value(),ui->sbBase->value()))
    {
        //profile not valid to program
        return;
    }

    profile.writeRamp = (ui->cbWriteRamp->checkState()==Qt::Checked);
    profile.verifyFinal = (ui->cbVerifyAll->checkState()==Qt::Checked);
    profile.verifySector = (ui->cbVerifySector->checkState()==Qt::Checked);

    if (fileToWrite.validConfig)
    {
        // spi port primary 0
        profile.spiport = primarySpiPort;
        profile.FileToSend = fileToWrite.primaryFile;
        profile.FileToSend2 = fileToWrite.secondaryFile;
        profile.write2Flash = true;

        QString address = QString("0x%1 - 0x%2").arg(profile.user_address_start_area, 0, 16). arg(profile.user_address_stop_area, 0, 16);
        QString msg = QString(STR_START_WORK).arg(fileToWrite.targetFlash).arg("primary").arg(address);
        addToLog(msg);

        /*//"... on %1 - spi port: %2 - address: %3."

        programWithProfile(checked);

        // spi port secondary 1
        profile.spiport = secondarySpiPort;
        profile.FileToSend = fileToWrite.secondaryFile;*/

        address = QString("0x%1 - 0x%2").arg(profile.user_address_start_area, 0, 16). arg(profile.user_address_stop_area, 0, 16);
        msg = QString(STR_START_WORK).arg(fileToWrite.targetFlash).arg("secondary").arg(address);
        addToLog(msg);

        programWithProfile(checked);
    }
    else
    {
        profile.FileToSend = ui->leFile->text();
        profile.FileToSend2 = "";
        profile.write2Flash = false;

        QString msg = "";
        QString address = QString("0x%1 - 0x%2").arg(profile.user_address_start_area, 0, 16). arg(profile.user_address_stop_area, 0, 16);

        //controllo se si tratta di fpga dell'rfif
        if (!profile.isFpgaRFIF)
        {
            //Se non lo è allora devo selezionare il canale spi dove installare
            QInputDialog qDialogSpiPort ;

            QStringList items;
            items << QString("Primary");
            items << QString("Secondary");

            qDialogSpiPort.setComboBoxItems(items);
            qDialogSpiPort.setWindowTitle("SPI");
            qDialogSpiPort.setLabelText("Select spi-port: ");

            if (qDialogSpiPort.exec())
            {
                QString value = qDialogSpiPort.textValue();
                if (value=="Primary")
                {
                    profile.spiport = primarySpiPort;
                    msg = QString(STR_START_WORK).arg(fileToWrite.targetFlash).arg("primary").arg(address);
                }
                else
                {
                    profile.spiport = secondarySpiPort;
                    msg = QString(STR_START_WORK).arg(fileToWrite.targetFlash).arg("secondary").arg(address);
                }
            }
            else
            {
                startEnabled(true);
                ui->btnWrite->setText("START");
                ui->btnWrite->setStyleSheet("QPushButton { background-color: green; color:white; }\n"
                                        "QPushButton:enabled { background-color: rgb(0,200,0); color:white; }\n");
                return;
            }

        }
        else    //se si tratta della fpga dell'rfif allora devo configurare il profilo di download in altra maniera
        {
            //Se non lo è allora devo selezionare il canale spi dove installare
            QInputDialog qDialogSpiPort ;

            QStringList items;
            items << QString("GOLDEN");
            items << QString("UPDATE");

            qDialogSpiPort.setComboBoxItems(items);
            qDialogSpiPort.setWindowTitle("");
            qDialogSpiPort.setLabelText("Select which part of RFIF fpga: ");

            if (qDialogSpiPort.exec())
            {
                QString value = qDialogSpiPort.textValue();
                if (value=="GOLDEN")
                {
                    profile.spiport = primarySpiPort;
                    address = QString("0x%1 - 0x%2").arg(profile.golden_address_start_area, 0, 16). arg(profile.golden_address_stop_area, 0, 16);
                    msg = QString(STR_START_WORK).arg(fileToWrite.targetFlash).arg("GOLDEN").arg(address);
                }
                else
                {
                    profile.spiport = secondarySpiPort;
                    address = QString("0x%1 - 0x%2").arg(profile.user_address_start_area, 0, 16). arg(profile.user_address_stop_area, 0, 16);
                    msg = QString(STR_START_WORK).arg(fileToWrite.targetFlash).arg("UPDATE").arg(address);
                }
            }
            else
            {
                startEnabled(true);
                ui->btnWrite->setText("START");
                ui->btnWrite->setStyleSheet("QPushButton { background-color: green; color:white; }\n"
                                        "QPushButton:enabled { background-color: rgb(0,200,0); color:white; }\n");
                return;
            }

            //profile.spiport = primarySpiPort;
            //msg = QString(STR_START_WORK).arg(fileToWrite.targetFlash).arg("NC").arg(address);
        }
        addToLog(msg);

        programWithProfile(checked);
    }
}

void QgGrifoBeamUpForm::statusUpdated(int sts, int progress, const QString& msg)
{
    if (sts==s_erase || sts==s_write || sts==s_read)
    {
        ui->lbOperation->setText(QString("%1").arg(msg));
    }
    else
    {
        addToLog(msg,sts);
    }
    if (progress>0)
        ui->progressBar->setValue(progress);


}

void QgGrifoBeamUpForm::on_btnStart_clicked()
{

}

void QgGrifoBeamUpForm::on_btnReset_clicked()
{
    //indivisuare il profilo da usare per le operazione di programmazione
    if (!getProfile(ui->sbSectorSize->value(),ui->sbBase->value()))
    {
        //profile not valid to program
        return;
    }
    profile.FileToSend = ui->leFile->text();

    programmer->reset(profile);
}

void QgGrifoBeamUpForm::on_btnErase_clicked()
{
    programmer->erase(1, ui->sbSectorSize->value(), ui->sbBase->value());
}

void QgGrifoBeamUpForm::on_btnFlashID_clicked()
{
    //indivisuare il profilo da usare per le operazione di programmazione
    if (!getProfile(ui->sbSectorSize->value(),ui->sbBase->value()))
    {
        //profile not valid to program
        return;
    }
    profile.FileToSend = ui->leFile->text();
    programmer->readFlashID(profile);
}

void QgGrifoBeamUpForm::on_btnGetStatus_clicked()
{
    //indivisuare il profilo da usare per le operazione di programmazione
    if (!getProfile(ui->sbSectorSize->value(),ui->sbBase->value()))
    {
        //profile not valid to program
        return;
    }
    profile.FileToSend = ui->leFile->text();
    programmer->readStatusSPI(profile);
}

void QgGrifoBeamUpForm::on_btnFinish_clicked()
{
    //indivisuare il profilo da usare per le operazione di programmazione
    if (!getProfile(ui->sbSectorSize->value(),ui->sbBase->value()))
    {
        //profile not valid to program
        return;
    }
    profile.FileToSend = ui->leFile->text();
    programmer->terminate(profile);
}

void QgGrifoBeamUpForm::on_cbSimulate_clicked(bool checked)
{
    programmer->setSimulate(checked);
}

void QgGrifoBeamUpForm::on_tbGo_clicked()
{

}

void QgGrifoBeamUpForm::clearTargets()
{
    memset(&targets, 0, sizeof targets);
}

//***********************************************************************
// update Grifo Download Site
// Input parameters:    checked = true if I also have to view the golden area of the flash
//                                false if I have to display only the user area of the flash
// Returns:
//***********************************************************************
void QgGrifoBeamUpForm::updateGrifoDownloadSite(Qt::CheckState checked)
{
    //clear targets struct
    clearTargets();

    //clear treewidget for targets
    entitiesForm->clear();

    //for every targets read from configuration files
    for (int i = 0; i<flashTargets->countTarget(); i++)
    {
        //TgtMatch tgt = tgtMatchSet.db[i];
        targetItem tgt = flashTargets->getTarget(i);

        if ((checked==Qt::Checked))
            //||
            //(checked==Qt::Unchecked && tgt.firmware_area!=flash_firmware_area_golden))
        {
            MyDebug.logMsg(type_log_info,
                             origin_msg_generic,
                             QString("%1 %2 %3 %4").arg(tgt.name).arg(tgt.slotAddress).arg(tgt.description).arg(tgt.filePrefix));

            {//Site
                QgGrifoDownloadSite* s=&targets.sites[targets.valid];

                memset(&s->site, 0, sizeof s->site);
                bsk_download_site_t* site=&s->site;
                strncpy(site->address, tgt.slotAddress.toLatin1(), sizeof site->address);

                s->tgtFlash=&tgt;

                s->site.media_address=QHostAddress(flashTargets->getDefIp()).toIPv4Address();
                s->site.media_port=flashTargets->getDefPort();

                strncpy(s->site.name, tgt.name.toLatin1().constData(), sizeof s->site.name);
                ++targets.valid;

                entitiesForm->addSite(s);
            }
        }
    }
}

void QgGrifoBeamUpForm::on_cb_GoldenFlash_stateChanged()
{
    updateGrifoDownloadSite(ui->cb_GoldenFlash->checkState());
}

//***********************************************************************
// Show target info
// Input parameters:
//                      popup = display the dialog box
// Returns:             the complete string of target information
//***********************************************************************
QString QgGrifoBeamUpForm::ShowTargetInfo(bool popup)
{
    QString fName = entitiesForm->getFirstSelectedTarget();

    const targetItem* tgt=flashTargets->getFromName(fName);

    if (!tgt)
        return QString("");

    QString infoText=
            "Target: <b>"+fName+"</b><p/>\n"
            +" &emsp;&emsp;Description: <b>"+QString("%1").arg(tgt->description)+"</b><p/>\n"
            +" &emsp;&emsp;Name: <b>"+QString("%1").arg(tgt->name)+"</b><p/>\n"
            +" &emsp;&emsp;Arch: <b>"+QString("%1").arg(tgt->arch)+"</b><p/>\n"
            +" &emsp;&emsp;Slot Address: <b>"+QString("%1").arg(tgt->slotAddress)+"</b><p/>\n"
            +"   &emsp;&emsp;IP:PORT: <b>"+QString("%1").arg(flashTargets->getDefIp())+":"+QString("%1").arg(flashTargets->getDefPort())+"</b><p/>\n"
            +"  <p/>\n"
            +" FLASH: <p/>\n";

    if (tgt->model.type==flash_type_xcku040)
    {
        infoText+= "   ->&emsp;&emsp;Type: <b> XCKU040 </b><p/>\n";
    }
    else
    if(tgt->model.type==flash_type_xcku060)
    {
        infoText+= "   ->&emsp;&emsp;Type: <b> XCKU060 </b><p/>\n";
    }
    else
    {
        infoText+= "   ->&emsp;&emsp;Type: <b> XC7A200 </b><p/>\n";
    }

    if (tgt->model.byte3_4==bytes3address)
    {
        infoText+= "   ->&emsp;&emsp;Address: <b> 3 bytes address </b><p/>\n";
    }
    else
    {
        infoText+= "   ->&emsp;&emsp;Address: <b> 4 bytes address </b><p/>\n";
    }

    infoText+= "   ->&emsp;&emsp;GOLDEN Start-Stop address: <b>"+QString("%1").arg(tgt->model.goldenAddressStartArea)+"-"+QString("%1").arg(tgt->model.goldenAddressStopArea)+"</b><p/>\n";

    infoText+= "   ->&emsp;&emsp;USER Start-Stop address: <b>"+QString("%1").arg(tgt->model.userAddressStartArea)+"-"+QString("%1").arg(tgt->model.userAddressStopArea)+"</b><p/>\n";


    if (popup)
        QMessageBox::information(0, "Target: "+fName, infoText);
    return infoText;
}



void QgGrifoBeamUpForm::on_btnGetTargetInfo_clicked()
{
    ShowTargetInfo(true);
}

//***********************************************************************
// Set profile, read information form selected fpga
// Input parameters:
// Returns:
//***********************************************************************
bool QgGrifoBeamUpForm::getProfile(unsigned int sectorSize,
                                   unsigned int baseOffset)
{
    QString fName = entitiesForm->getFirstSelectedTarget();

    const targetItem *tgt = flashTargets->getFromName(fName);

    if (!tgt)
    {
        return false;
    }

    profile.fName = fName;

    bool bStatus= false;
    profile.user_address_start_area = QString(tgt->model.userAddressStartArea).toUInt(&bStatus, 16);
    if (!bStatus)
    {
        return false;
    }
    profile.user_address_stop_area = QString(tgt->model.userAddressStopArea).toUInt(&bStatus, 16);
    if (!bStatus)
    {
        return false;
    }
    profile.golden_address_start_area = QString(tgt->model.goldenAddressStartArea).toUInt(&bStatus, 16);
    if (!bStatus)
    {
        return false;
    }
    profile.golden_address_stop_area = QString(tgt->model.goldenAddressStopArea).toUInt(&bStatus, 16);
    if (!bStatus)
    {
        return false;
    }
    profile.BaseAddress = QString(tgt->model.userAddressStartArea).toUInt(&bStatus, 16);
    if (!bStatus)
    {
        return false;
    }
    profile.BaseOffset = baseOffset;
    profile.byteddress = (reg_moder_byteaddress_t)tgt->model.byte3_4;
    profile.ip = flashTargets->getDefIp();
    profile.port = QString("%1").arg(flashTargets->getDefPort());
    profile.SectorSize_KBytes = sectorSize;
    profile.slotAddress = tgt->slotAddress;
    //profile.spiport = tgt->spiPort;

    /*if (tgt->model->type==flash_type_xcku040)
    {
        //xcku040
        profile.dimMbit = FLASH_128Mbit;
    }
    else
    {
        //xc7a200 and xcku060
        profile.dimMbit = FLASH_256Mbit;
    }*/

    profile.writeRamp = (ui->cbWriteRamp->checkState()==Qt::Checked);
    profile.verifyFinal = (ui->cbVerifyAll->checkState()==Qt::Checked);
    profile.verifySector = (ui->cbVerifySector->checkState()==Qt::Checked);

    fileToWrite.targetFlash = tgt->filePrefix;

    profile.isFpgaRFIF = false;

    if (tgt->model.idModel==AESA_RFIF_MODEL)
        profile.isFpgaRFIF = true;

    return true;
}

void QgGrifoBeamUpForm::on_cb_TargetAddress_clicked(bool checked)
{
    programmer->setSRIOMemory(checked);
}

void QgGrifoBeamUpForm::on_btnGetValue_clicked()
{
    QString address = ui->sbGetValue->text();
    unsigned int len=256;
    char data[len];

    uint32_t dataInt[256];

    //legge mediante srio un valore presente in memoria all'indirizzo indicato
    QString remoteFile=QString("$SRIO:%1/%2+%3").arg(profile.slotAddress).arg(address, 0, 16).arg(len);


    MyDebug.logMsg(type_log_info,
                         origin_msg_srio,
                         QString("Command %1").arg(remoteFile));


    try
    {
        Q_EMIT programmer->readRequest(remoteFile, dataInt, len);

        //programmer->waitRxEvent();
    }
    catch (...)
    {
        MyDebug.logMsg(type_log_error,
                             origin_msg_tftp,
                             "not inizialized");
    }

    sprintf (data, "0x%8.8lX", (long unsigned int)dataInt[0]);

    ui->lblGetValue->setText(data);
}

void QgGrifoBeamUpForm::on_btnMem_clicked()
{
    ui->sbGetValue->setText(QString("0x%1").arg(BASE_ADDRESS_MEM,0,16));
}

void QgGrifoBeamUpForm::on_btnFPGA_clicked()
{
    ui->sbGetValue->setText(QString("0x%1").arg(BASE_ADDRESS_IF,0,16));
}

void QgGrifoBeamUpForm::on_btnHistory_clicked()
{
    _dbHistory->refreshList();
    HistoryDBForm HistoryDBWindow;

    HistoryDBWindow.setWindowTitle("History DB");

    HistoryDBWindow.setDB(_dbHistory);
    HistoryDBWindow.exec();
}

void QgGrifoBeamUpForm::on_btnAddHistory_clicked()
{
    //(QString _file, db_error_t _error, QString _where)
    QString fileName = ui->leFile->text();
    db_error_t _error = db_error_t(ui->cbError->currentIndex());
    db_status_t _status = db_status_t(ui->cbStatus->currentIndex());
    QString fName = entitiesForm->getFirstSelectedTarget();

    const targetItem* tgt=flashTargets->getFromName(fName);

    if (!tgt)
        return;

    QString address = QString("%1-%2").arg(tgt->model.userAddressStartArea).arg(tgt->model.userAddressStopArea);
    QString srio = QString("%1@%2:%3").arg(tgt->slotAddress).arg(flashTargets->getDefIp()).arg(flashTargets->getDefPort());
    int spi = int(profile.spiport);

    _dbHistory->addNewFile(fileName,
                           _error,
                           fName,
                           _status,
                           address,
                           srio,
                           spi);
}

void QgGrifoBeamUpForm::on_tbRefresh_clicked()
{

}

void QgGrifoBeamUpForm::on_tbHistory_clicked()
{
    on_btnHistory_clicked();
}

void QgGrifoBeamUpForm::on_tbFileSelect_clicked()
{

}

void QgGrifoBeamUpForm::startEnabled(bool _status)
{

   ui->tbRefresh->setEnabled(_status);
   ui->tbFileSelect->setEnabled(_status);
   ui->tbFileInfo->setEnabled(_status);
   ui->tbHistory->setEnabled(_status);
   entitiesForm->setEnabled(_status);
}

void QgGrifoBeamUpForm::on_btnWrite_clicked()
{
    //check if connected
    if (!IS_TFTP_CONNECTED)
    {
        QMessageBox::warning(0, STR_TITLE_SERVER, STR_SERVER_IS_NOT_CONNECTED);
        return;
    }

    //check if one target is selected
    QString fName = entitiesForm->getFirstSelectedTarget();
    if (fName=="")
    {
        QMessageBox::warning(0, STR_TITLE_SELECTION, STR_SELECTION_NOT_VALID);
        return;
    }

    //check if selected file exists
    QFileInfo finfo(ui->leFile->text());
    if (!finfo.exists())
    {
        QMessageBox::critical(0, "ERROR open file", "File <p/>"+ui->leFile->text() +"<p/> is not available.");
        return;
    }

    if (ui->btnWrite->text()=="START")
    {
        ui->btnWrite->setText("STOP");
        startEnabled(false);
        on_btnStart_clicked(true);
        ui->btnWrite->setStyleSheet("QPushButton { background-color: red; color:white; }\n"
                                    "QPushButton:enabled { background-color: rgb(200,0,0); color:white; }\n");
    }
    else
    {
        startEnabled(true);
        ui->btnWrite->setText("START");
        ui->btnWrite->setStyleSheet("QPushButton { background-color: green; color:white; }\n"
                                    "QPushButton:enabled { background-color: rgb(0,200,0); color:white; }\n");
    }

}

/********************************************************************
 * extract info about fpga-flash to programme with this file
 * Input parameters:   complete file zip path
 * Return:             true if config is ok
 *                     false if config is not ok
 */
bool QgGrifoBeamUpForm::extractInfoFromZip(QString _fileName)
{

    resetFileToWrite();

    //check if tmp folder is already created
    if (QDir(TMP_FOLDER).exists())
    {
        //delete tmp folder
        if (QDir(TMP_FOLDER).removeRecursively())
        {
            MyDebug.logMsg(type_log_info,
                             origin_msg_generic,
                             "Tmp folder deleted.");
        }
        else
        {
            MyDebug.logMsg(type_log_error,
                             origin_msg_generic,
                             "Tmp folder is not deleted.");
        }
    }
    if (!QDir().mkdir(TMP_FOLDER))
    {
        MyDebug.logMsg(type_log_error,
                         origin_msg_history,
                         QString("ERROR create tmp folder %1").arg(TMP_FOLDER));
        return false;
    }

    //extract info from zip to tmp folder

    QZipReader zipfile(_fileName);

    if(zipfile.count()!=0)
    {
        for (int i = 0; i<zipfile.count(); i++)
        {
            QZipReader::FileInfo fileItem;
            fileItem = zipfile.entryInfoAt(i);
            MyDebug.logMsg(type_log_info,
                             origin_msg_generic,
                             QString("file%1 %2").arg(i).arg(fileItem.filePath));

        }
    }

    //extract all files into tmp folder
    if (!zipfile.extractAll(TMP_FOLDER))
    {
        MyDebug.logMsg(type_log_error,
                         origin_msg_generic,
                         QString("ERROR unzip file: %1").arg(_fileName));
        return false;
    }

    //extract info from xml file
    QString fileXml = TMP_FOLDER+"/info.xml";


    fpagFlashXmlClass fpagFlashXml;
    fpagFlashXml.setXmlFile(fileXml);

    if (!fpagFlashXml.readXML())
    {
        MyDebug.logMsg(type_log_error,
                         origin_msg_generic,
                         QString("ERROR xml file: %1").arg(fileXml));
        return false;
    }

    fileToWrite.primaryFile = TMP_FOLDER+ "/" +fpagFlashXml.getPrimaryFile();
    fileToWrite.secondaryFile = TMP_FOLDER+ "/" +fpagFlashXml.getSecondaryFile();
    fileToWrite.primaryMD5 = fpagFlashXml.getPrimaryMD5();
    fileToWrite.secondaryMD5 = fpagFlashXml.getSecondaryMD5();

    //check binary files with md5 present into xml file
    if (!checkMD5(fileToWrite.primaryFile, fileToWrite.primaryMD5))
    {
        MyDebug.logMsg(type_log_error,
                         origin_msg_generic,
                         QString("ERROR primary MD5 file: %1").arg(fileToWrite.primaryFile));
        return false;
    }

    if (!checkMD5(fileToWrite.secondaryFile, fileToWrite.secondaryMD5))
    {
        MyDebug.logMsg(type_log_error,
                         origin_msg_generic,
                         QString("ERROR secondary MD5 file: %1").arg(fileToWrite.secondaryFile));
        return false;
    }

    fileToWrite.validConfig = true;

    fileToWrite.targetFlash = fpagFlashXml.getTarget();

    return true;
}

void QgGrifoBeamUpForm::setColorLog(QPlainTextEdit *logtext,Qt::GlobalColor newColor, Qt::GlobalColor newBckColor )
{
    QTextCharFormat tf = logtext->currentCharFormat();
    tf.setForeground(QBrush(newColor));
    tf.setBackground(QBrush(newBckColor));
    logtext->setCurrentCharFormat(tf);
}

void QgGrifoBeamUpForm::addToLog(QString _msg, unsigned int sts)
{
    QString tick = QDateTime::currentDateTime().toString("hh:mm:ss.zzz");

    switch (sts)
    {
        case s_init:
        case s_status:
        case s_read_id:
        case s_erase:
        case s_write:
        default:
            ui->leMsg->appendPlainText(QString("%1 - %2").arg(tick).arg(_msg));
            break;
        case s_error:
            setColorLog(ui->leMsg, Qt::red, Qt::black);
            ui->leMsg->appendPlainText(QString("%1 - %2").arg(tick).arg(_msg));
            setColorLog(ui->leMsg, Qt::black, Qt::white);
            break;
        case s_end:
            setColorLog(ui->leMsg, Qt::green,Qt::black);
            ui->leMsg->appendPlainText(QString("%1 - %2").arg(tick).arg(_msg));
            setColorLog(ui->leMsg, Qt::black,Qt::white);
            break;
        case s_question:
            setColorLog(ui->leMsg, Qt::cyan,Qt::black);
            ui->leMsg->appendPlainText(QString("%1 - %2").arg(tick).arg(_msg));
            setColorLog(ui->leMsg, Qt::black,Qt::white);
            break;
        case s_warning:
            setColorLog(ui->leMsg, Qt::yellow,Qt::black);
            ui->leMsg->appendPlainText(QString("%1 - %2").arg(tick).arg(_msg));
            setColorLog(ui->leMsg, Qt::black,Qt::white);
            break;
    }

}

void QgGrifoBeamUpForm::setTargetOnScreen()
{
    unsigned int numTargets = flashTargets->countTarget();

    targetItem tgt;
    for (unsigned int i=0; i<numTargets; i++)
    {
        tgt = flashTargets->getTarget(i);
        MyDebug.logMsg(type_log_info,
                         origin_msg_generic,
                         QString("%1 %2 %3 %4").arg(tgt.g).arg(tgt.name).arg(tgt.slotAddress).arg(tgt.arch));

        {//Site

            QgGrifoDownloadSite* s=&targets.sites[targets.valid];

            memset(&s->site, 0, sizeof s->site);

            bsk_download_site_t* site=&s->site;

            strncpy(site->address, tgt.slotAddress.toLatin1(), sizeof site->address);

            s->tgtFlash             = &tgt;
            s->site.media_address   = QHostAddress(flashTargets->getDefIp()).toIPv4Address();
            s->site.media_port      = flashTargets->getDefPort();

            strncpy(s->site.name, tgt.name.toLatin1().constData(), sizeof s->site.name);

            ++targets.valid;

            entitiesForm->addSite(s);

        }//Site
    }
    entitiesForm->setDefaultTarget(flashTargets->getDefTarget());
    entitiesForm->setVisible(true);
}
