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

#include "logicfamily.h"
#include "mainwindow.h"
#include "utils.h"
#include "proputils.h"

QMap<QString, logicFamily_t> LogicFamily::m_families;

LogicFamily::LogicFamily()
{
    m_blocked = false;
    m_enableSupply = true;

    m_supplyV  = 5.0; // Power Supply
    m_inpHighVp = 0.5;
    m_inpHighV  = 2.5;
    m_inpLowVp  = 0.5;
    m_inpLowV   = 2.5;
    m_outHighVp = 1;
    m_outHighV  = 5;
    m_outLowVp  = 0;
    m_outLowV   = 0;

    m_inpImp = 1e9;
    m_outImp = 40;

    m_delayMult = 1;
    m_delayBase = 10*1000; // 10 ns
    m_timeLH    = 3000;
    m_timeHL    = 4000;

    m_family = "Custom";
    if( m_families.isEmpty() ) getFamilies();
}
LogicFamily::~LogicFamily(){}

void LogicFamily::setInpHighV( double v )
{
    if( m_blocked ) return;
    m_inpHighVp = v/m_supplyV;
}

void LogicFamily::setInpLowV( double v )
{
    if( m_blocked ) return;
    m_inpLowVp = v/m_supplyV;
}

void LogicFamily::setOutHighV( double v )
{
    if( m_blocked ) return;
    m_outHighVp = v/m_supplyV;
}

void LogicFamily::setOutLowV( double v )
{
    if( m_blocked ) return;
    m_outLowVp = v/m_supplyV;
}

void LogicFamily::setPropDelay( double pd )
{
    if( pd < 0 ) pd = 0;
    if( pd > 1e6   ) pd = 1e6;
    m_delayBase = pd*1e12;
}

void LogicFamily::setRiseTime( double time )
{
    if( time < 1e-12 ) time = 1e-12;
    if( time > 1e6   ) time = 1e6;
    m_timeLH = time*1e12;
}

void LogicFamily::setFallTime( double time )
{
    if( time < 1e-12 ) time = 1e-12;
    if( time > 1e6   ) time = 1e6;
    m_timeHL = time*1e12;
}

void LogicFamily::setFamily( QString f )
{
    m_family = f;
    if( f == "Custom") setSupplyV( m_supplyV );
    else               setFamilyData( m_families.value( f ) );
}

void LogicFamily::setFamilyData( logicFamily_t lf )
{
    double supplyV = lf.supply;
    m_enableSupply = supplyV < 0;
    if( !m_enableSupply ) m_supplyV = supplyV;

    setSupplyV( m_supplyV );

    m_inpHighVp = lf.inpLHp;
    m_inpLowVp  = lf.inpHLp;
    m_inpImp    = lf.inpImp;

    m_outHighVp = lf.outHip;
    m_outLowVp  = lf.outLop;
    m_outImp    = lf.outImp;

    updateData();
}

void LogicFamily::updateData()
{
    m_blocked = true;

    setInpHighV( m_supplyV * m_inpHighVp );
    setInpLowV(  m_supplyV * m_inpLowVp );
    setInputImp( m_inpImp );
    setInpPullups( m_inpPullups );

    setOutHighV( m_supplyV * m_outHighVp);
    setOutLowV(  m_supplyV * m_outLowVp );
    setOutImp(   m_outImp );
    setOutPullups( m_outPullups );
    m_blocked = false;
}

void LogicFamily::getFamilies() // Static
{
    m_families["Default"] = { -1, 0.5, 0.5, 1e9, 0, 1, 0, 40, 0 };
    m_families["Custom"]  = { -1, 0.5, 0.5, 1e9, 0, 1, 0, 40, 0 };

    QString modelsFile = MainWindow::self()->getDataFilePath("logic_families.model");
    if( !QFile::exists( modelsFile ) ) return;

    QString doc = fileToString( modelsFile, "LogicFamily::getFamilies()" );

    QStringList docLines = doc.split(QChar('\n'));
    for( QString line : docLines )
    {
        QVector<propStr_t> properties = parseProps( line );
        if( properties.isEmpty() ) break;
        QString familyName = properties.takeFirst().name;
        logicFamily_t family;

        for (const propStr_t& property : properties)
        {
            QString propName = property.name;
            double propValue = property.value.toDouble();

            if     ( propName == u"supply") family.supply = propValue;
            else if( propName == u"inpLHp") family.inpLHp = propValue;
            else if( propName == u"inpHLp") family.inpHLp = propValue;
            else if( propName == u"inpImp") family.inpImp = propValue;
            else if( propName == u"inpPul") family.inpPul = propValue;
            else if( propName == u"outHip") family.outHip = propValue;
            else if( propName == u"outLop") family.outLop = propValue;
            else if( propName == u"outImp") family.outImp = propValue;
            else if( propName == u"outPul") family.outPul = propValue;
        }
        m_families[familyName] = family;
    }
    /*QVector<QStringRef> docLines = doc.splitRef("\n");
    for( QStringRef line : docLines )
    {
        QVector<propStr_t> properties = parseProps( line );
        if( properties.isEmpty() ) break;
        QString familyName = properties.takeFirst().name.toString();
        logicFamily_t family;

        for( propStr_t property : properties )
        {
            QStringRef propName = property.name;
            double  propValue = property.value.toDouble();
            if     ( propName == "supply") family.supply = propValue;
            else if( propName == "inpLHp") family.inpLHp = propValue;
            else if( propName == "inpHLp") family.inpHLp = propValue;
            else if( propName == "inpImp") family.inpImp = propValue;
            else if( propName == "inpPul") family.inpPul = propValue;
            else if( propName == "outHip") family.outHip = propValue;
            else if( propName == "outLop") family.outLop = propValue;
            else if( propName == "outImp") family.outImp = propValue;
            else if( propName == "outPul") family.outPul = propValue;
        }
        m_families[familyName] = family;
    }*/
}
