#include "adsmonitorwidget.h"
#include "ui_adsmonitorwidget.h"

#include "ads_data.h"

//#include <QGraphicsView>

#include <QComboBox>

//#include <QPolygonF>
//#include <QGraphicsScene>
//#include <QGraphicsItemGroup>

#include <QDebug>
#include <QTimer>
#include <QVector>
#include <QTreeWidgetItem>
#include <QTableWidgetItem>

//#include <adsplotwidget.h>

#include <qadsplot.h>

#include <math.h>
#include <float.h>

static QString toHex(unsigned int n)
{
    unsigned int i=n;
    return QString("%1").arg(i, 4, 16);
}

static QString sts1553ToStr(avb_1553_sts_word_t sts)
{
    return QString("%1-%2-%3").arg(sts.str.rt).arg(sts.str.me).arg(sts.raw & 0x03FF, 4, 16);
}

static QString cmd1553ToStr(avb_1553_cmd_word_t cmd)
{
  return QString("%1-%2-%3-%4").arg(cmd.str.rt).arg(cmd.str.tr ? "T" : "R").arg(cmd.str.sa).arg(cmd.str.wc);
}

class AdsMonitorCheckerItem: public QTreeWidgetItem
{
public:
  static void setHeaders(QTreeWidget& t)
  {
    t.setHeaderLabels(
        QStringList()<<"Name"<<"Check"<<"Fails"<<"delay"<<"duration"<<"reason");
  }
  AdsMonitorCheckerItem(Ads1553MessageCheck& c, QTreeWidget& w):
      chk(c)
  {
    setData(0, Qt::DisplayRole, chk.name());
    setToolTip(0, chk.description());

    w.addTopLevelItem(this);
  }

  void update()
  {
    setData(1, Qt::DisplayRole, chk.checks());

    setData(2, Qt::DisplayRole, chk.fails());
    setData(3, Qt::DisplayRole, double(chk.delayTime())/1000.0);
    setData(4, Qt::DisplayRole, double(chk.durationTime())/1000.0);
    setData(5, Qt::DisplayRole, chk.lastFailReason());
  }

  Ads1553MessageCheck& chk;
};

class AdsMonitorWidget::Private
{
public:
  enum { gfx_max_data=4};
  enum { gfx_panes=4};

  class MsgListTreeItem: public QTreeWidgetItem
  {
  public:
    static void setHeaders(QTreeWidget& t)
    {
      t.setHeaderLabels(
        QStringList()<<"C"<<"Name"<<"CW"<<"SW"<<"Num"<<"Errs"<<"period"<<"wc"<<"MC"<<"xerr"
      );
    }
    MsgListTreeItem()
    {
      setCheckState(0, Qt::PartiallyChecked);
      setCheckState(1, Qt::PartiallyChecked);
    }

    void attachTo(QTreeWidget& t, Ads1553MessageStatus& sts)
    {
      setData(1, Qt::DisplayRole, sts.name());
      setToolTip(1, sts.longName());

      setData(2, Qt::DisplayRole, cmd1553ToStr(sts.cw()));
      setToolTip(2, toHex(sts.cw().raw));
      sts.setClientCookie(this);

      t.addTopLevelItem(this);
      for(int i=0; i<3; ++i)
        t.resizeColumnToContents(i);
    }

    void update(Ads1553MessageStatus& sts)
    {

      if (!sts.updated())
        return;

      if (sts.lastIsNoResponse())
          setData(3, Qt::DisplayRole, "N/R");
      else
        setData(3, Qt::DisplayRole, sts1553ToStr(sts.lastSW()));
      setData(4, Qt::DisplayRole, sts.numOfMessages());
      setData(5, Qt::DisplayRole, sts.errors());
      setData(6, Qt::DisplayRole, sts.deltaTimeMs());
      setData(7, Qt::DisplayRole, sts.transferedWc());
      if (sts.cw().str.sa==0 || sts.cw().str.sa==31)
      {
        if (sts.transferedWc()>0)
          setData(8, Qt::DisplayRole, toHex(sts.contents()[0]));
      }
      setData(9, Qt::DisplayRole, toHex(sts.rawErrorCode()));
      sts.resetUpdated();
    }
  };

  class TermListTreeItem: public QTreeWidgetItem
  {
  public:
    static void setHeaders(QTreeWidget& t)
    {
      t.setHeaderLabels(QStringList()<<"Name"<<"ADR"<<"Msg"<<"Errs"<<"RX"<<"TX"<<"N/R"<<"Last SW"<<"xerr");
    }
    TermListTreeItem()
    {
    }

    void attachTo(QTreeWidget& t, Ads1553TerminalStatus& sts)
    {
      setData(0, Qt::DisplayRole, sts.name());
      setToolTip(0, sts.longName());

      setData(1, Qt::DisplayRole, sts.address());

      sts.setClientCookie(this);

      t.addTopLevelItem(this);
      for(int i=0; i<2; ++i)
        t.resizeColumnToContents(i);
    }

    void update(Ads1553TerminalStatus& sts)
    {

      if (!sts.updated())
        return;

      setData(2, Qt::DisplayRole, sts.numOfMessages());
      setData(3, Qt::DisplayRole, sts.errors());
      setData(4, Qt::DisplayRole, sts.received());
      setData(5, Qt::DisplayRole, sts.transmitted());
      setData(6, Qt::DisplayRole, sts.noResponse());
      setData(7, Qt::DisplayRole, sts1553ToStr(sts.lastSW()));
      setData(8, Qt::DisplayRole, toHex(sts.rawErrorCode()));

      sts.resetUpdated();
    }
  };

  Private(AdsMonitorWidget& w_):
      w(w_)
  {
    //gfx.gset=new AdsPlotWidgetSet;
  }


  void setUp()
  {
    /*
    gfx.table=0; //w.ui->tableWidget;

    gfx.g[0]=w.ui->graphicsView_1;
    gfx.g[1]=w.ui->graphicsView_2;
    gfx.g[2]=w.ui->graphicsView_3;
    gfx.g[3]=w.ui->graphicsView_4;

    gfx.cbD[0]=w.ui->cbD1;
    gfx.cbD[1]=w.ui->cbD2;
    gfx.cbD[2]=w.ui->cbD3;
    gfx.cbD[3]=w.ui->cbD4;

    gfx.cbS[0]=w.ui->cbScale1;
    gfx.cbS[1]=w.ui->cbScale2;
    gfx.cbS[2]=w.ui->cbScale3;
    gfx.cbS[3]=w.ui->cbScale4;

    gfx.cbG[0]=w.ui->cbG1;
    gfx.cbG[1]=w.ui->cbG2;
    gfx.cbG[2]=w.ui->cbG3;
    gfx.cbG[3]=w.ui->cbG4;

    gfx.sbVA[0]=w.ui->sbVA1;
    gfx.sbVA[1]=w.ui->sbVA2;
    gfx.sbVA[2]=w.ui->sbVA3;
    gfx.sbVA[3]=w.ui->sbVA4;

    gfx.sbVB[0]=w.ui->sbVB1;
    gfx.sbVB[1]=w.ui->sbVB2;
    gfx.sbVB[2]=w.ui->sbVB3;
    gfx.sbVB[3]=w.ui->sbVB4;

    gfx.sbC[0]=w.ui->sbTA;
    gfx.sbC[1]=w.ui->sbTB;

    for(int i=0; i<4; ++i)
    {
      gfx.sbVA[i]->setDecimals(6);
      gfx.sbVA[i]->setRange(-1.0e+50, 1.0e+50);
      gfx.sbVB[i]->setDecimals(6);
      gfx.sbVB[i]->setRange(-1.0e+50, 1.0e+50);
    }
    for(int i=0; i<2; ++i)
    {
      gfx.sbC[i]->setDecimals(3);
      gfx.sbC[i]->setRange(-1.0e+50, 1.0e+50);
    }

    for(int i=0; i<gfx_max_data; ++i)
    {
      gfx.cbG[i]->insertItem(0, QString("<hiden>"));
      for(int x=0; x<gfx_panes; ++x)
      {
        gfx.cbG[i]->insertItem(x+1, QString("Pane%1").arg(x+1));
      }
      gfx.cbG[i]->insertItem(gfx_panes+1, QString("Table"));

      gfx.cbG[i]->setCurrentIndex(0);

      for(int x=0; x<gfx_max_data; ++x)
        gfx.cbS[i]->insertItem(x, QString("SC%1").arg(x+1));
      gfx.cbS[i]->setCurrentIndex(0);

      connect(gfx.cbG[i], SIGNAL(currentIndexChanged(int)), &w, SLOT(updateGraphicPaneVisibility(int)));
    }
    for(int i=0; i<gfx_panes; ++i)
    {
      gfx.ena_counter[i]=0;
      gfx.g[i]->setVisible(false);
      //gfx.vD[i]=0;
      gfx.gset->addWidget(gfx.g[i]);
    }

    gfx.ena_table=0;
    gfx.table->setVisible(false);

    gfx.table->setSortingEnabled(false);
    gfx.table->setRowCount(1);
    gfx.table->setColumnCount(6);
    gfx.table->setHorizontalHeaderLabels(QStringList()<<"Time"<<"<data1>"<<"<data2>"<<"<data3>"<<"<data4>"<<"<caculated>");
    gfx.table->setVerticalHeaderLabels(QStringList()<<"...");
    gfx.table->setItem(0, 0, new QTableWidgetItem("..."));

    updateGraphicPaneVisibility();
    */
  }

  void updateGraphicPaneVisibility()
  {
    /*
    bool at_least_one=false;
    for(int i=0; i<gfx_panes; ++i)
    {
      gfx.ena_counter[i]=0;
      gfx.ena_table=0;
    }

    for(int i=0; i<gfx_max_data; ++i)
    {
      int n=gfx.cbG[i]->currentIndex();
      if (n>0 && n<=gfx_panes)
      {
        at_least_one=true;
        ++gfx.ena_counter[n-1];
      }
      else if (n==gfx_panes+1)
      {
        ++gfx.ena_table;
        at_least_one=true;
      }
    }
    for(int i=0; i<gfx_panes; ++i)
    {
      gfx.g[i]->setVisible(gfx.ena_counter[i]>0);
      gfx.g[i]->setEnabled(gfx.ena_counter[i]>0);

    }
    gfx.table->setVisible(gfx.ena_table>0);
    gfx.table->setEnabled(gfx.ena_table>0);

    w.ui->graphicsView_dummy->setVisible(!at_least_one);
    w.ui->graphicsView_dummy->setEnabled(at_least_one);
    */
  }

  typedef struct {
    QTableWidget* table;

    /*
    AdsPlotWidget* g[gfx_panes];
    AdsPlotWidgetSet* gset;

    QComboBox* cbD[gfx_max_data];
    QComboBox* cbG[gfx_max_data];
    QComboBox* cbS[gfx_max_data];

    QDoubleSpinBox* sbVA[gfx_max_data];
    QDoubleSpinBox* sbVB[gfx_max_data];
    QDoubleSpinBox* sbC[2];

    int ena_counter[gfx_panes];
    */
    int ena_table;

    //QGraphicsItemGroup* vD[gfx_panes];

  } gfx_t;
  gfx_t gfx;

  AdsMonitorWidget& w;

  QAdsPlotWidget* qpw;
  QStandardItemModel* data_model;
};

AdsMonitorWidget::AdsMonitorWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::AdsMonitorWidget),
    p_(*new Private(*this))
{
    ui->setupUi(this);

    Private::TermListTreeItem::setHeaders(*ui->treeWidgetTerminals);
    Private::MsgListTreeItem::setHeaders(*(ui->treeWidgetTraffic));

    AdsMonitorCheckerItem::setHeaders(*(ui->twChecks));

    ui->treeWidgetStack->setColumnCount(32+5);
    {
      QStringList headers(QStringList()<<"#"<<"Time"<<"delta"<<"CW"<<"SW");
      for(int i=1; i<=32; ++i)
        headers.append(QString("W%1").arg(i));
      ui->treeWidgetStack->setHeaderLabels(headers);  //TODO: fix size
      for(int i=0; i<=32+5; ++i)
        ui->treeWidgetStack->resizeColumnToContents(i);

    }

    p_.setUp();

    p_.qpw=new QAdsPlotWidget;
    ui->tbHistoryView->insertItem(0, p_.qpw, "Plot");
    ui->tbHistoryView->setCurrentIndex(0);

    ui->toolBox->setCurrentIndex(0);

    ui->spinBox_Tot->setRange(INT_MIN, INT_MAX);
    ui->spinBox_iLost->setRange(INT_MIN, INT_MAX);
    ui->spinBox_iRaised->setRange(INT_MIN, INT_MAX);
    ui->spinBox_iSrv->setRange(INT_MIN, INT_MAX);
    ui->spinBox_Frames->setRange(INT_MIN, INT_MAX);
    ui->spinBox_FrameTT->setRange(DBL_MIN+1, DBL_MAX);
    ui->spinBox_FrameTT->setDecimals(6);

    /*
    ui->sbCD->setDecimals(3);
    ui->sbCD->setRange(-1.0e+50, 1.0e+50);

    connect(p_.gfx.gset, SIGNAL(cursorMoved(double,uint)), SLOT(_onGfxCursorPos(double,uint)));
    */

    p_.data_model=new QStandardItemModel;

    for(int i=0; i<8; ++i)
    {
      connect(p_.qpw->channelSelctor(i), SIGNAL(clicked()), SLOT(plotSourceSelection()));
    }

    connectToManager();
}

bool AdsMonitorWidget::connectToManager()
{
  connect(&Ads1553Manager::instance(), SIGNAL(terminalListChanged()), SLOT(_onTerminalListChanged()));
  connect(&Ads1553Manager::instance(), SIGNAL(runStatusChanged(Ads1553Manager::run_sts_t)), SLOT(_onRunStatusChanged(Ads1553Manager::run_sts_t)));
  connect(&Ads1553Manager::instance(), SIGNAL(messageListChanged()), SLOT(_onMessageListChanged()));
  connect(&Ads1553Manager::instance(), SIGNAL(monitorUpdated(avb_1553_monitor_info_t*)), SLOT(_onMonitorUpdated(avb_1553_monitor_info_t*)));
  connect(&Ads1553Manager::instance(), SIGNAL(acqUpdated(bool,uint)), SLOT(_onAcqUpdated(bool,uint)));
  connect(&Ads1553Manager::instance(), SIGNAL(checkAdded(Ads1553MessageCheck&)), SLOT(_onCheckAdded(Ads1553MessageCheck&)));

  return true;
}

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

void AdsMonitorWidget::plotSourceSelection()
{
  for(int ch_num=0; ch_num<8; ++ch_num)
  {
    if (p_.qpw->channelSelctor(ch_num)==sender())
    {
      QString title=QString("Source for ch%1").arg(ch_num);
      QTreeInputDialog d(title);
      d.setModel(p_.data_model);
      if (d.exec()==QDialog::Accepted)
      {
        p_.qpw->setChannelName(ch_num, d.w->currentIndex().data().toString(), (void*)d.w->currentIndex().data(Qt::UserRole+1).toUInt());
        p_.qpw->setChannelEnabled(ch_num, true);
      }
    }
  }
}

void AdsMonitorWidget::updateGraphicPaneVisibility(int)
{
  p_.updateGraphicPaneVisibility();
}

void AdsMonitorWidget::_onTerminalListChanged()
{
  int n=Ads1553Manager::instance().numOfTerminals();
  for(int i=0; i<n; ++i)
  {
    avb_1553_terminal_t* const t=Ads1553Manager::instance().getTerminal(i);
    if (!t)
      break;
    unsigned int rt=t->adr;

    if (rt<1 || rt>30)
      continue;

    Ads1553TerminalStatus* ts=Ads1553Manager::instance().terminalStatus(rt);
    if (!ts || !ts->valid())
      continue;

    Private::TermListTreeItem* ti=new Private::TermListTreeItem;
    ti->attachTo(*ui->treeWidgetTerminals, *ts);
    /*
    p_.tList[rt].init(t);
    if (rt!=0)
    {
      ui->treeWidgetTerminals->addTopLevelItem(&p_.tList[rt].item);
    }
    else
      p_.tList[rt].valid=false;
    */
  }
}

void AdsMonitorWidget::_onMessageListChanged()
{
  //int n=Ads1553Manager::instance().numOfMessages();
  unsigned int n=Ads1553Manager::instance().numOfDynMessage();

  for(unsigned int i=0; i<n; ++i)
  {
    //Ads1553MsgQ* msg=Ads1553Manager::instance().getMsgObj(i);
    Ads1553MessageStatus* msg=Ads1553Manager::instance().messageStatusByIndex(i);

    if (msg->getClientCookie()==0)
    {
      Private::MsgListTreeItem* n=new Private::MsgListTreeItem;
      n->attachTo(*ui->treeWidgetTraffic, *msg);
      //ui->treeWidgetTraffic->addTopLevelItem(&(n->item));
    }
  }
}

void AdsMonitorWidget::updateDataList()
{
  //Update data lists
  /*
  for(int x=0; x<p_.gfx_max_data; ++x)
  {
    p_.gfx.cbD[x]->clear();
    p_.gfx.cbD[x]->addItem("<no-data>", (unsigned int)0);
  }
  */

  unsigned int n=AdsDataManager::logicDataCount();

  p_.data_model->clear();
  QStandardItem* unclass_items=0; //new QStandardItem("Unclassified");
  //p_.data_model->appendRow(unclass_items);

  QStandardItem* raw_items=new QStandardItem("<RAW>");
  //p_.data_model->appendRow(unclass_items);

  for(unsigned int i=0; i<n; ++i)
  {
    AdsLogicData* d=AdsDataManager::getLogicData(i);
    if (!d)
      continue;

    /*
    for(int x=0; x<p_.gfx_max_data; ++x)
    {
      p_.gfx.cbD[x]->addItem(d->objectName(), (unsigned int)d);
    }
    */
    Ads1553MsgQ* rawmsg=d->getMsg();


    if (!rawmsg)
    {
      if (!unclass_items)
        unclass_items=new QStandardItem("Unclassified");
      QStandardItem* si=new QStandardItem(d->objectName());
      si->setData((int)d);
      unclass_items->appendRow(si);
    }
    else
    {
      const QString tmp=rawmsg->objectName();
      QList<QStandardItem*> ilist=p_.data_model->findItems(tmp);
      if (ilist.size()==1)
      {
        if (p_.data_model->findItems(d->objectName()).size()==0)
        {
          QStandardItem* si=new QStandardItem(d->objectName());
          si->setData((int)d);
          ilist[0]->appendRow(si);
        }
      }
      else
      {
        QStandardItem* iparent=new QStandardItem(tmp);
        p_.data_model->appendRow(iparent);
        QStandardItem* si=new QStandardItem(d->objectName());
        si->setData((int)d);
        iparent->appendRow(si);
      }
    }
  }
  p_.data_model->appendRow(raw_items);
  if (unclass_items)
    p_.data_model->appendRow(unclass_items);
}

void AdsMonitorWidget::_onRunStatusChanged(Ads1553Manager::run_sts_t sts)
{
  setEnabled(sts>Ads1553Manager::sts_device_err);
}

void AdsMonitorWidget::_onMonitorUpdated(avb_1553_monitor_info_t *info)
{
    ui->treeWidgetTerminals->setUpdatesEnabled(false);
    ui->treeWidgetTraffic->setUpdatesEnabled(false);

    unsigned int n=Ads1553Manager::instance().numOfDynMessage();

    for(unsigned int i=0; i<n; ++i)
    {
      //Ads1553MsgQ* msg=Ads1553Manager::instance().getMsgObj(i);
      Ads1553MessageStatus* msg=Ads1553Manager::instance().messageStatusByIndex(i);

      Private::MsgListTreeItem* n=reinterpret_cast<Private::MsgListTreeItem*>(msg->getClientCookie());

      if (!n)
      {
        n=new Private::MsgListTreeItem;
        n->attachTo(*ui->treeWidgetTraffic, *msg);
        //ui->treeWidgetTraffic->addTopLevelItem(&(n->item));
      }
      n->update(*msg);
    }

    //n=Ads1553Manager::instance().numOfTerminals();
    for(unsigned int i=1; i<31; ++i)
    {
      Ads1553TerminalStatus* const ts=Ads1553Manager::instance().terminalStatus(i);

      if (!ts || !ts->valid())
        continue;

      Private::TermListTreeItem* n=reinterpret_cast<Private::TermListTreeItem*>(ts->getClientCookie());
      if (!n)
      {
        n=new Private::TermListTreeItem;
        n->attachTo(*ui->treeWidgetTerminals, *ts);
      }
      n->update(*ts);
    }

    ui->treeWidgetTerminals->setUpdatesEnabled(true);
    ui->treeWidgetTraffic->setUpdatesEnabled(true);

    {
      avb_1553_intr_status_t sts=Ads1553Manager::instance().getDriver()->getIntrStatus();
      ui->spinBox_Frames->setValue(sts.major_frames);
      ui->spinBox_FrameTT->setValue(double(sts.major_frame_tt)/1000000.0);
      ui->spinBox_iSrv->setValue(sts.served);
      ui->spinBox_iRaised->setValue(sts.raised);

      ui->spinBox_Tot->setValue(info->total_message);
    }
}

void AdsMonitorWidget::on_pushButton_Acq_toggled(bool checked)
{
  if (checked)
  {
    Ads1553Manager::instance().acqStart();
    p_.qpw->setRealtimeMode(true);
  }
  else
  {
    Ads1553Manager::instance().acqStop();
    p_.qpw->setRealtimeMode(false);
  }
}

struct drcx_t {
  bool data_changed_stack;
  bool data_changed_gfx;

  Ads1553AcqAnalyzer* a;
  unsigned int max;
  unsigned int pos;
  unsigned long previous_tt;

  double tt_min;
  double tt_max;
  bool tt_init;

  //AdsPlotSamples samples[4];
  AdsLogicData* d[4];

  int pane[4];
};

static drcx_t drcx;

void AdsMonitorWidget::_stackRefresh()
{

  if (drcx.pos==0)
  {
    //ui->tbHistoryView->setDisabled(true);
    ui->pbRefresh->setDisabled(true);
    ui->pushButton_Acq->setDisabled(true);
    if (drcx.data_changed_stack)
      ui->treeWidgetStack->clear();
    /*
    if (drcx.data_changed_gfx)
    {
      for(int n=0; n<p_.gfx_max_data; ++n)
      {
        drcx.d[n]=0;
        drcx.pane[n]=-1;

        int i=p_.gfx.cbD[n]->currentIndex();
        if (i<0)
          continue;
        if (p_.gfx.cbG[n]->currentIndex()<=0)
          continue;
        drcx.pane[n]=p_.gfx.cbG[n]->currentIndex()-1;

        drcx.d[n]=reinterpret_cast<AdsLogicData*>(p_.gfx.cbD[n]->itemData(i).toUInt());
      }

      for(int i=0; i<4; ++i)
        drcx.samples[i].clear();
      drcx.tt_init=true;
    }
    */
    p_.qpw->clear();
  }

  for(int cycle=10; cycle>0 && drcx.pos<drcx.max; ++drcx.pos)
  {
    const ads_acq_data_t& acq=drcx.a->get(drcx.pos);
    const avb_1553_mon_decoded_t& decoded=acq.decoded;

    //Updated stack
    if (drcx.data_changed_stack && ui->pageMessageHistory->isVisible())
    {
      QTreeWidgetItem* i=new QTreeWidgetItem;
      i->setData(0, Qt::DisplayRole, drcx.pos);
      if (drcx.pos==0)
        drcx.previous_tt=decoded.timetag;

      unsigned long delta_tt=decoded.timetag-drcx.previous_tt;

      drcx.previous_tt=decoded.timetag;

      i->setData(1, Qt::DisplayRole, (unsigned int)decoded.timetag);
      i->setData(2, Qt::DisplayRole, (unsigned int)delta_tt);
      i->setData(3, Qt::DisplayRole, cmd1553ToStr(decoded.cmd));
      i->setData(4, Qt::DisplayRole, sts1553ToStr(decoded.sts));
      for(unsigned int w=0; w<decoded.wc; ++w)
        i->setData(5+w, Qt::DisplayRole, toHex(decoded.data[w]));

      ui->treeWidgetStack->addTopLevelItem(i);
    }

    {
      for(int i=0; i<8; ++i)
      {
        AdsLogicData* td=reinterpret_cast<AdsLogicData*>(p_.qpw->channelUserData(i));
        if (!td)
          continue;
        Ads1553MsgQ* m=td->getMsg();
        if (!m)
          continue;

        if (m==acq.msg)
        {
          double y=td->cvFromExtern(&decoded.data[0]);
          double x=double(decoded.timetag)/1000000.0;
          p_.qpw->addData(i, x, y);
        }
        //p_.qpw->addData(i, d.decoded.timetag/1000000.0, (d.decoded.timetag & 0x00FFFF));
      }
      //p_.qpw->updateData();
    }

    /*
    if (drcx.data_changed_gfx && ui->pageGraphic->isVisible())
    {
      for(int i=0; i<4; ++i)
      {
        if (!drcx.d[i])
          continue;

        Ads1553MsgQ* m=drcx.d[i]->getMsg();
        if (!m)
          continue;

        if (m==acq.msg)
        {
          double y=drcx.d[i]->cvFromExtern(&decoded.data[0]);
          double x=double(decoded.timetag)/1000.0;
          drcx.samples[i].addSample(x, y);

          if (drcx.tt_init)
          {
            drcx.tt_init=false;
            drcx.tt_min=x;
          }
          drcx.tt_max=x;
        }
      }
    }
    */
  }

  //p_.qpw->updateData();

  if (drcx.pos<drcx.max)
    QTimer::singleShot(50, this, SLOT(_stackRefresh()));
  else
  {
    /*
    if (ui->pageGraphic->isVisible())
    {
      static const Qt::GlobalColor colors[][2]=
      {{Qt::darkBlue, Qt::blue},
       {Qt::darkGreen, Qt::green},
       {Qt::darkRed, Qt::red},
       {Qt::darkYellow, Qt::yellow}};

      drcx.data_changed_gfx=false;

      p_.gfx.gset->clear();

      p_.gfx.gset->setRangeX(drcx.tt_min, drcx.tt_max);

      for(int n=0; n<4; ++n)
      {
        int p=p_.gfx.cbG[n]->currentIndex()-1;

        if (p<0)
          continue;
        if (drcx.samples[n].samples()<=0)
          continue;
        int si=p_.gfx.cbS[n]->currentIndex();

        p_.gfx.g[p]->addSamples(drcx.samples[n], si, colors[n][0]);
      }
      p_.gfx.gset->update();

    }
    */
    if (ui->pageMessageHistory->isVisible())
    {
      drcx.data_changed_stack=false;
    }

    ui->tbHistoryView->setDisabled(false);
    ui->pbRefresh->setDisabled(false);
    ui->pushButton_Acq->setDisabled(false);

    p_.qpw->rescaleAll();
    p_.qpw->updateData();
  }
}

void AdsMonitorWidget::_onAcqUpdated(bool in_progress, unsigned int filled_percentage)
{
  static unsigned int last_pos=0;
  ui->progressBar_Acq->setValue(filled_percentage);
  ui->pushButton_Acq->setChecked(in_progress);

  if (in_progress)
  {
    //ui->tbHistoryView->setDisabled(true);
    ui->pbRefresh->setDisabled(true);

    Ads1553AcqAnalyzer& aa=Ads1553Manager::instance().getAcqAnalyzer();
    unsigned int max=aa.items();
    if (max<last_pos)
      last_pos=0;
    for(; last_pos<max; ++last_pos)
    {
      const ads_acq_data_t& d=aa.get(last_pos);

      //if (d.decoded.cmd.str.sa==4)
      {
        for(int i=0; i<8; ++i)
        {
          AdsLogicData* td=reinterpret_cast<AdsLogicData*>(p_.qpw->channelUserData(i));
          if (!td)
            continue;
          Ads1553MsgQ* m=td->getMsg();
          if (!m)
            continue;

          if (m==d.msg)
          {
            double y=td->cvFromExtern(&d.decoded.data[0]);
            double x=double(d.decoded.timetag)/1000000.0;
            p_.qpw->addData(i, x, y);
          }
          //p_.qpw->addData(i, d.decoded.timetag/1000000.0, (d.decoded.timetag & 0x00FFFF));
        }
        p_.qpw->updateData();
      }
    }
    return;
  }

  if (filled_percentage>0)
  {
    drcx.data_changed_stack=true;
    drcx.data_changed_gfx=true;
    Ads1553AcqAnalyzer& aa=Ads1553Manager::instance().getAcqAnalyzer();
    drcx.a=&aa;
    drcx.max=aa.items();
    drcx.pos=0;
    //QTimer::singleShot(10, this, SLOT(_stackRefresh()));
    ui->pbRefresh->setDisabled(false);
  }
}

void AdsMonitorWidget::on_pbRefresh_clicked()
{
  drcx.pos=0;
  drcx.data_changed_gfx=true;
  drcx.data_changed_stack=true;
  _stackRefresh();
}

void AdsMonitorWidget::on_tbHistoryView_currentChanged(int /*index*/)
{
  on_pbRefresh_clicked();
}

void AdsMonitorWidget::on_tbZoomIn_clicked()
{
  //p_.gfx.gset->zoomIn();
}

void AdsMonitorWidget::on_tbZoomOut_clicked()
{
  //p_.gfx.gset->zoomOut();
}

void AdsMonitorWidget::_onGfxCursorPos(double /*x*/, unsigned int /*crs*/)
{
  /*
  if (crs>2)
    return;
  p_.gfx.sbC[crs]->setValue(x);
  ui->sbCD->setValue(p_.gfx.sbC[1]->value()-p_.gfx.sbC[0]->value());

  QDoubleSpinBox** s= crs==0 ? &p_.gfx.sbVA[0] : &p_.gfx.sbVB[0];
  //x=x+drcx.tt_min;
  for(int i=0; i<4; ++i)
  {
    //s[i]->setValue(drcx.samples[i].valueAt(x));
    s[i]->setValue(drcx.samples[i].valueAtOffset(x));
  }
  */
}

void AdsMonitorWidget::_onCheckAdded(Ads1553MessageCheck &chk)
{
  chk.setCookie(new AdsMonitorCheckerItem(chk, *ui->twChecks));
  chk.updated.ads_connect(this, _onCheckUpdated);
}

void AdsMonitorWidget::on_pbChecksRefresh_clicked()
{
  int n=ui->twChecks->topLevelItemCount();
  for(int i=0; i<n; ++i)
  {
    QTreeWidgetItem* item=ui->twChecks->topLevelItem(i);
    AdsMonitorCheckerItem* ci=reinterpret_cast<AdsMonitorCheckerItem*>(item);
    ci->update();
  }
}

ADS_SLOT_IMPLEMENT(AdsMonitorWidget, _onCheckUpdated, (Ads1553MessageCheck& chk), (chk))
{
  AdsMonitorCheckerItem* ci=reinterpret_cast<AdsMonitorCheckerItem*>(chk.getCookie());
  if (ci)
    ci->update();
}

void AdsMonitorWidget::on_pushButton_Acq_clicked()
{

}
