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

#include "logiccomponent.h"
#include "circuitwidget.h"
#include "simulator.h"
#include "connector.h"
#include "circuit.h"
#include "iopin.h"

#define tr(str) simulideTr("LogicComponent",str)

const QString LogicComponent::m_triggerList = "None,Clock,Enable; "+tr("None")+","+tr("Clock")+","+tr("Enable"); 

LogicComponent::LogicComponent( QString type, QString id )
              : IoComponent( type, id )
              , eClockedDevice( id )
{
    m_oePin     = nullptr; 
    m_tristate  = false; 
    m_outEnable = true; 
}
LogicComponent::~LogicComponent(){}

void LogicComponent::stamp()
{
    IoComponent::initState(); 
    eClockedDevice::stamp(); 
    if( m_oePin ) m_oePin->changeCallBack( this ); 
    m_outEnable = true; 

    voltChanged(); 
}

std::vector<Pin*> LogicComponent::getPins()
{
    std::vector<Pin*> pins = IoComponent::getPins(); 
    if( m_oePin  ) pins.emplace_back( m_oePin ); 
    if( m_clkPin ) pins.emplace_back( m_clkPin ); 
    return pins; 
}

void LogicComponent::remove()
{
    if( m_oePin ) m_oePin->removeConnector(); 
    eClockedDevice::remove(); 
    IoComponent::remove(); 
}

void LogicComponent::setOePin( IoPin* pin )
{
    m_oePin = pin; 
    pin->setInverted( true ); 
    m_oePin->setLabelText("OE "); 
}

bool LogicComponent::outputEnabled()
{
    if( !m_oePin ) return true; 

    m_outEnable = m_oePin->getInpState(); 
    return m_outEnable; 
}

void LogicComponent::updateOutEnabled()
{
    if( !m_oePin ) return; 

    bool outEnPrev = m_outEnable; 
    bool outEn = outputEnabled();               // Refresh m_outEnable
    if( outEnPrev != outEn ) enableOutputs( outEn ); 
}

void LogicComponent::setTristate( bool t )  // Activate or deactivate OE Pin
{
    if( !m_oePin ) return; 

    if( !t ) m_oePin->removeConnector(); 

    m_oePin->setVisible( t ); 
    m_tristate = t; 
    updateOutEnabled(); 
}

void LogicComponent::setTriggerStr( QString t )
{
    m_triggerStr = t; 

    trigger_t trigger = Clock; 
    if     ( t == "None"  ) trigger = None; 
    else if( t == "Clock" ) trigger = Clock; 
    else if( t == "Enable") trigger = InEnable; 

    setTrigger( trigger ); 

    if( m_showVal && (m_showProperty == "Trigger") )
        setValLabelText( t ); 
}

void LogicComponent::enableOutputs( bool en )
{
    for( uint i=0;  i<m_outPin.size();  ++i ) m_outPin[i]->setStateZ( !en ); 
}

void LogicComponent::setInpHighV( double volt )
{
    IoComponent::setInpHighV( volt ); 
    if( m_clkPin) m_clkPin->setInputHighV( m_inpHighV ); 
}

void LogicComponent::setInpLowV( double volt )
{
    IoComponent::setInpLowV( volt ); 
    if( m_clkPin) m_clkPin->setInputLowV( m_inpLowV ); 
}

void LogicComponent::setInputImp( double imp )
{
    IoComponent::setInputImp( imp ); 
    Simulator::self()->pauseSim(); 
    if( m_clkPin) m_clkPin->setInputImp( m_inpImp ); 
    Simulator::self()->resumeSim(); 
}
