/***************************************************************************
 *   Copyright (C) 2025 by Santiago González                               *
 *                                                                         *
 ***( see copyright.txt file at root folder )*******************************/

#include "analogclock.h"
#include "simulator.h"
#include "e-reactive.h"
#include "circuitwidget.h"

AnalogClock* AnalogClock::m_pSelf = nullptr;

AnalogClock::AnalogClock()
           : eElement("AnalogClock")
{
    m_pSelf = this;
    m_clkElement = nullptr;
    m_divider = 1;
    m_period = m_step = 1e6;
}
AnalogClock::~AnalogClock(){}

void AnalogClock::stamp()
{
    setDivider( 1 );
    if( m_clkElement ) Simulator::self()->addEvent( m_period, this );
}

void AnalogClock::updateStep()
{
    if( !m_changed ) return;
    m_changed = false;
    CircuitWidget::self()->updtAppDialog();
}

void AnalogClock::runEvent()
{
    eElement* clkElement = m_clkElement;
    while( clkElement )
    {
        clkElement->runEvent();
        clkElement = clkElement->nextEvent;
    }
    Simulator::self()->addEvent( m_step, this );
}

void AnalogClock::addClkElement( eElement* e )
{
    e->nextEvent = m_clkElement;
    m_clkElement = e;
}

void AnalogClock::remClkElement( eElement* e )
{
    eElement* clkElement = m_clkElement;
    eElement* lastElement = nullptr;
    eElement* nextElement = nullptr;

    while( clkElement )
    {
        if( clkElement == e )
        {
            nextElement = clkElement->nextEvent;
            if( lastElement ) lastElement->nextEvent = nextElement;
            else              m_clkElement = nextElement;
            clkElement->nextEvent = nullptr;
            return;
        }
        lastElement = clkElement;
        clkElement = clkElement->nextEvent;
    }
}

void AnalogClock::setPeriod( uint64_t p )
{
    m_period = p;
    m_step = m_period/m_divider;
}

void AnalogClock::setDivider( uint64_t d )
{
    m_divider = d;
    m_step = m_period/m_divider;
    m_changed = true;
}
