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

#include <QPainter>

#include "bus.h"
#include "connector.h"
#include "simulator.h"
#include "circuit.h"
#include "circuitwidget.h"
#include "itemlibrary.h"
#include "e-node.h"

#include "intprop.h"

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

Component* Bus::construct( QString type, QString id )
{ return new Bus( type, id );  }

LibraryItem* Bus::libraryItem()
{
    return new LibraryItem(
        tr("Bus"),
        "Connectors",
        "bus.png",
        "Bus",
        Bus::construct ); 
}

Bus::Bus( QString type, QString id )
   : Component( type, id )
   , eElement( id )
{
    m_busPin1 = new Pin( 270, QPoint( 0, 0 ), m_id+"-busPinI", 1, this ); 
    m_busPin1->setFlag( QGraphicsItem::ItemStacksBehindParent, false ); 
    m_busPin1->setLength( 1 ); 
    m_busPin1->setIsBus( true ); 

    m_numLines = 0; 
    m_startBit = 0; 
    setNumLines( 8 );        // Create Input Pins

    m_ePin[0] = m_pin[0] = m_busPin0 = new Pin( 90, QPoint( 0, 0 ), m_id+"-ePin0", 1, this ); 
    m_busPin0->setFlag( QGraphicsItem::ItemStacksBehindParent, false ); 
    m_busPin0->setLength( 1 ); 
    m_busPin0->setIsBus( true ); 

    addPropGroup( { tr("Main"), {
        new IntProp<Bus>("Num_Bits" , tr("Size"),"_bits"
                        , this, &Bus::numLines, &Bus::setNumLines, propNoCopy,"uint" ),

        new IntProp<Bus>("Start_Bit", tr("Start Bit"),""
                        , this, &Bus::startBit, &Bus::setStartBit,0,"uint" )
    }, groupNoCopy } ); 
}
Bus::~Bus(){}

void Bus::registerEnode( eNode* enode, int n )
{
    if( m_busPin0->conPin() ) m_busPin0->registerPinsW( enode, n ); 
    if( m_busPin1->conPin() ) m_busPin1->registerPinsW( enode, n ); 

    int i = n + 1 - m_startBit; 
    if( i < 0 ) return; 
    if( i > m_numLines ) return; 

    if( m_pin[i]->conPin() ) m_pin[i]->registerPinsW( enode, -1 ); 
}

void Bus::setNumLines( int lines )
{
    if( Simulator::self()->isRunning() ) CircuitWidget::self()->powerCircOff(); 

    if( lines == m_numLines ) return; 
    if( lines < 1 ) return; 

    for( int i=1;  i<=m_numLines;  i++ ) deletePin( m_pin[i] ); 

    m_numLines = lines; 

    m_pin.resize( lines+2 ); 
    m_ePin.resize( lines+2 ); 
    m_signalPin.clear(); 
    
    for( int i=1;  i<=lines;  i++ )
    {
        QString pinId = m_id+"-ePin"+QString::number(i); 
        Pin* pin = new Pin( 180, QPoint(-8, -8*lines+i*8 ), pinId, m_startBit+i-1, this ); 

        pin->setFontSize( 4 ); 
        pin->setLabelColor( QColor( 0, 0, 0 ) ); 
        pin->setLabelText( " "+QString::number( m_startBit+i-1 )+" " ); 
        m_pin[i]  = pin; 
        m_ePin[i] = pin; 
        m_signalPin.append( pin ); 
    }
    m_busPin1->setPos( QPoint( 0 ,-lines*8+8 ) ); 
    m_busPin1->isMoved(); 
    m_pin[ lines+1 ]  = m_busPin1; 
    m_ePin[ lines+1 ] = m_busPin1; 

    m_height = lines-1; 
    m_area = QRect( -3,-m_height*8-2, 5, m_height*8+4 ); 

    setflip(); 
    Circuit::self()->update(); 
}

void Bus::setStartBit( int bit )
{
    if( Simulator::self()->isRunning() ) CircuitWidget::self()->powerCircOff(); 
    if( bit < 0 ) bit = 0; 
    m_startBit = bit; 

    for( int i=1;  i<=m_numLines;  i++ )
    {
        m_pin[i]->setIndex( m_startBit+i-1 ); 
        m_pin[i]->setLabelText( " "+QString::number( m_startBit+i-1 ) ); 
    }
}

void Bus::paint( QPainter* p, const QStyleOptionGraphicsItem* option, QWidget* widget )
{
    Component::paint( p, option, widget ); 

    QPen pen = p->pen(); 
    pen.setWidth(3); 
    p->setPen(pen); 

    p->drawRect( QRect( 0, -m_height*8, 0, m_height*8 ) ); 
              //QRect( -2, -m_height*8-4, 2, m_height*8+8 ); 

    Component::paintSelected( p ); 
}
