#include "AdcBlockReceiver.h"
#include "LQMeasStudio.h"
#include "DataBlockProcessPlugin.h"
#include "lmath.h"

namespace LQMeasStudio {
    AdcBlockReceiver::AdcBlockReceiver() : m_procBlockTime(25), m_procBlockInterval(1000) {

    }

    void AdcBlockReceiver::start() {
        foreach (AdcReceiver *receiver, LQMeasStudioEnv->inLauncher()->adcReceivers()) {
            connect(receiver, SIGNAL(dataReceived(QList<QSharedPointer<AdcReceiver::Data> >)),
                    SLOT(processData(QList<QSharedPointer<AdcReceiver::Data> >)));
        }

        foreach (QSharedPointer<ChannelInfo> ch, LQMeasStudioEnv->channelsConfig()->channels()) {
            m_chProcInfo[ch->num()] = new ChProcInfo();
        }
    }

    void AdcBlockReceiver::stop() {
        foreach (AdcReceiver *receiver, LQMeasStudioEnv->inLauncher()->adcReceivers()) {
            disconnect(receiver, SIGNAL(dataReceived(QList<QSharedPointer<AdcReceiver::Data> >)),
                    this,SLOT(processData(QList<QSharedPointer<AdcReceiver::Data> >)));

        }
    }

    void AdcBlockReceiver::clear() {
        qDeleteAll(m_chProcInfo);
        m_chProcInfo.clear();
    }

    void AdcBlockReceiver::setBlockTime(double blockTime, double intervalTime) {
        m_procBlockTime = blockTime;
        m_procBlockInterval = qMax(blockTime, intervalTime);
    }

    void AdcBlockReceiver::processData(QList<QSharedPointer<AdcReceiver::Data> > dataList) {
        QList<QSharedPointer<DataBlock> > blockList;

        foreach (QSharedPointer<AdcReceiver::Data> chData, dataList) {
             ChProcInfo *procInfo = m_chProcInfo[chData->ch->num()];
             LQMeas::DevAdc *adc = chData->ch->device()->devAdc();

             if (procInfo && adc) {
                unsigned show_pts = m_procBlockTime/(1000.* chData->dt) + 0.5;
                unsigned interval_pts = m_procBlockInterval/(1000. * chData->dt) + 0.5;
                unsigned proc_size = 0;
                if (show_pts < 2)
                    show_pts = 2;

                while (proc_size < (unsigned)chData->data.size()) {
                    if (!procInfo->block_sent) {
                        if (procInfo->proc_points < show_pts) {
                            unsigned add_size = qMin((chData->data.size()-proc_size),
                                                     (show_pts-procInfo->proc_points));
                            if (procInfo->proc_points == 0) {
                                procInfo->startX = chData->dt*(chData->x_idx + proc_size) + chData->ch->timeShift();
                            }

                            for (unsigned i=0; i < add_size; i++) {
                                procInfo->y.append(chData->data[proc_size + i]);
                            }
                            proc_size += add_size;
                            procInfo->proc_points += add_size;
                        }

                        if (procInfo->proc_points >= show_pts) {
                            QSharedPointer<DataBlock> dataBlock =
                                QSharedPointer<DataBlock>(new DataBlock(chData->ch,
                                    procInfo->y, procInfo->startX, chData->dt));
                            blockList.append(dataBlock);
                            procInfo->block_sent = true;
                        }
                    }

                    if (procInfo->block_sent) {
                        if (procInfo->proc_points < interval_pts) {
                            unsigned drop_size = qMin((chData->data.size()-proc_size),
                                                     (interval_pts-procInfo->proc_points));
                            proc_size += drop_size;
                            procInfo->proc_points+= drop_size;
                        }

                        if (procInfo->proc_points >= interval_pts) {
                            procInfo->proc_points = 0;
                            procInfo->y.clear();
                            procInfo->block_sent = false;
                        }
                    }
                }
            }
        }

        if (blockList.size()) {
            foreach (QSharedPointer<DataBlock> block, blockList) {
                foreach (ProcessPlugin *plugin, LQMeasStudioEnv->processPlugings()) {
                    DataBlockProcessPlugin *blockPlugin = dynamic_cast<DataBlockProcessPlugin *>(plugin);
                    if (blockPlugin && blockPlugin->procEnabled()) {
                        blockPlugin->blockProcess(block);
                    }
                }
            }
            emit receiveBlock(blockList);
        }
    }
}

