#include "qgscopechrono.h"

#include <QTimer>
#include <QList>

#include <windows.h>

static int chrono_timer_counter;

QgScopeChronoTimer::QgScopeChronoTimer(QObject *parent):
    QgScopeChronoTimer(QString("CHORNOTIMER_%1").arg(chrono_timer_counter), parent)
{
}

QgScopeChronoTimer::QgScopeChronoTimer(const QString &name, QObject *parent):
    QObject(parent),
    m_id(chrono_timer_counter),
    m_multiplier(1),
    m_frozen(false)
{
    setObjectName(name);
    m_timer=new QTimer(this);
    connect(m_timer, &QTimer::timeout, this, &QgScopeChronoTimer::onPeriodExpired);
    ++chrono_timer_counter;
}

QgScopeChronoTimer::QgScopeChronoTimer(const QgScopeChronoTimer& t):
    QgScopeChronoTimer(t.name(), t.parent())
{
    m_multiplier=t.m_multiplier;
    m_frozen=t.frozen();
}

void QgScopeChronoTimer::onPeriodExpired()
{
    if (m_multiplier<=1)
    {
        m_multiplier=QgScopeChrono::instance().multiplier();
        if (!QgScopeChrono::instance().frozen())
            Q_EMIT periodExpired();
    }
    --m_multiplier;
}

QgScopeChronoTimer::us_t QgScopeChronoTimer::timeNow()
{
    return QgScopeChrono::instance().timeNowUs();
}

void QgScopeChronoTimer::start(QgScopeChronoTimer::us_t period)
{
    unsigned long ms=float(period+500)/1000.0f;
    m_period=period;
    if (ms<=0)
        m_timer->stop();

    m_multiplier=QgScopeChrono::instance().multiplier();

    m_timer->start(ms);
}


void QgScopeChronoTimer::stop()
{
    m_timer->stop();
}

void QgScopeChronoTimer::restart()
{
    m_timer->start();
}

int QgScopeChronoTimer::id() const
{
    return m_id;
}

QString QgScopeChronoTimer::name() const
{
    return objectName();
}

bool QgScopeChronoTimer::frozen() const
{
    return !m_timer->isActive();
}

void QgScopeChronoTimer::setFreeze(bool freeze)
{
    if (freeze)
        stop();
    else if (!m_timer->isActive())
        restart();
    if (m_frozen==freeze)
    {
        m_frozen=freeze;
        Q_EMIT chronoFrozen(m_frozen);
    }
}

static unsigned long long chrono_base;

QgScopeChrono& QgScopeChrono::instance()
{
    static QgScopeChrono concreteInstance;
    return concreteInstance;
}

void QgScopeChrono::chronoStart(unsigned long long /*ms_resolutions*/)
{
   elapsedTimer.start();
   chrono_base=elapsedTimer.nsecsElapsed()/1000;
}

unsigned long long QgScopeChrono::timeNowUs() const
{
    if (!elapsedTimer.isValid())
    {
        QgScopeChrono* c=const_cast<QgScopeChrono*>(this);
        c->chronoStart(0);
    }
    unsigned long long t=elapsedTimer.nsecsElapsed()/1000;
    t=t/m_multiplier;
    return chrono_base+t;
}

unsigned int QgScopeChrono::multiplier() const
{
    return m_multiplier;
}

void QgScopeChrono::setMultiplier(unsigned int n)
{
    if ((n!=m_multiplier) && (n>0))
    {
        unsigned long long t=elapsedTimer.nsecsElapsed()/1000;
        chrono_base+=t*m_multiplier;
        m_multiplier=n;
        elapsedTimer.restart();
        Q_EMIT chronoMultiplierChanged(m_multiplier);
    }
}

void QgScopeChrono::step()
{

}

bool QgScopeChrono::frozen() const
{
    return m_frozen;
}

void QgScopeChrono::setFreeze(bool freeze)
{
    bool please_emit=m_frozen!=freeze;
    m_frozen=freeze;
    if (please_emit)
        Q_EMIT chronoFrozen(m_frozen);
}

QgScopeChrono::QgScopeChrono():
    QObject(0),
    m_multiplier(1),
    m_frozen(false)
{
    setObjectName("Chrono");
}

QgScopeChrono::~QgScopeChrono()
{
}



