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

#include <QPainter>
#include <math.h>

#include "sevensegment_bcd.h"
#include "itemlibrary.h"
#include "simulator.h"
#include "iopin.h"
#include "ledbase.h"

#include "boolprop.h"

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

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

LibraryItem* SevenSegmentBCD::libraryItem()
{
    return new LibraryItem(
        tr("7 Seg BCD"),
        "Other Logic",
        "7segbcd.png",
        "7 Seg BCD,7-Seg BCD",
        SevenSegmentBCD::construct );
}

SevenSegmentBCD::SevenSegmentBCD( QString type, QString id )
               : BcdBase( type, id )
{
    m_graphical = true;

    m_width  = 4;
    m_height = 6;
    m_color  = Qt::black;

    QStringList pinList;

    pinList // Inputs:
            << "ID041"
            << "ID032"
            << "ID024"
            << "ID018"
            << "IU04E"
            << "IU01."
            ;
    init( pinList );
    for( uint i=0; i<m_inpPin.size(); ++i )
    {
        m_inpPin[i]->setX( m_inpPin[i]->x()-4);
        m_inpPin[i]->setSpace( 1 );
        m_inpPin[i]->setFontSize( 4 );
        m_inpPin[i]->setLabelColor( QColor( 250, 250, 200 ) );
    }

    m_showEnablePin = false;
    m_enablePin = m_inpPin[4];
    m_enablePin->setInverted( true );
    m_enablePin->setVisible( false );

    m_showDotPin = false;
    m_dotPin = m_inpPin[5];
    m_dotPin->setVisible( false );

    setLabelPos(-16,-40, 0);

    addPropGroup( { tr("Main"), {
        new BoolProp<SevenSegmentBCD>("Show_Point_Pin", tr("Show Point Pin"),"", this
                              , &SevenSegmentBCD::isShowDotPin, &SevenSegmentBCD::setShowDotPin, propNoCopy ),

        new BoolProp<SevenSegmentBCD>("Show_Enable_Pin", tr("Show Enable Pin"),"", this
                              , &SevenSegmentBCD::isShowEnablePin, &SevenSegmentBCD::setShowEnablePin, propNoCopy )
    },groupNoCopy} );

    Simulator::self()->addToUpdateList( this );

    m_digit = 0;
}
SevenSegmentBCD::~SevenSegmentBCD(){}

void SevenSegmentBCD::updateStep()
{
    if( !m_changed ) return;
    m_changed = false;

    if( !Simulator::self()->isRunning() ) m_digit = 0;
    else if( !m_linkedTo ){
        if( m_enablePin->getInpState() ){
            BcdBase::voltChanged();
            if( m_dotPin->getInpState() ) m_digit |= 0x80;
        }
        else m_digit = 0;
    }
    update();
}

void SevenSegmentBCD::voltChanged() { m_changed = true; }

void SevenSegmentBCD::setShowEnablePin( bool show )
{
    if( m_showEnablePin == show ) return;
    m_showEnablePin = show;

    if( !show ) m_enablePin->removeConnector();
    m_enablePin->setVisible( show );
}

void SevenSegmentBCD::setShowDotPin( bool show )
{
    if( m_showDotPin == show) return;
    m_showDotPin = show;

    if( !show ) m_dotPin->removeConnector();
    m_dotPin->setVisible( show );
}

bool SevenSegmentBCD::setLinkedTo( Linker* li )
{
    bool linked = Component::setLinkedTo( li );
    if( li && linked )
        for( uint i=0; i<m_inpPin.size(); ++i ) m_inpPin[i]->removeConnector();

    setHidden( (li && linked), false, false );

    return linked;
}

void SevenSegmentBCD::setLinkedValue( double v, int i )
{
    int vInt = v;
    vInt &= 0xFF;
    if( i == 0 ) m_digit = m_segments[vInt]; // Display value
    else         m_digit = vInt;             // 1 bit for each segment
    m_changed = true;
}

void SevenSegmentBCD::paint( QPainter* p, const QStyleOptionGraphicsItem* o, QWidget* w )
{
    Component::paint( p, o, w );
    p->drawRect( m_area );

    const int mg =  6; // Margin around number
    const int ds =  1; // "Slope"
    const int tk =  4; // Line thickness
    const int x1 =  m_area.x()+mg;
    const int x2 = -m_area.x()-mg;
    const int y1 =  m_area.y()+mg;
    const int y2 = -m_area.y()-mg;

    QPen pen;
    pen.setWidth( tk );
    QColor color = LedBase::getColor( (LedBase::ledColor_t)0, 255 );
    pen.setColor( color );
    pen.setCapStyle( Qt::RoundCap );
    p->setPen( pen );

    if( m_digit & 1<<0 ) p->drawLine( x1+tk+ds, y1,    x2-tk+ds, y1    );
    if( m_digit & 1<<1 ) p->drawLine( x2+ds,    y1+tk, x2,      -tk    );
    if( m_digit & 1<<2 ) p->drawLine( x2,       tk,    x2-ds,    y2-tk );
    if( m_digit & 1<<3 ) p->drawLine( x2-tk-ds, y2,    x1+tk-ds, y2    );
    if( m_digit & 1<<4 ) p->drawLine( x1-ds,    y2-tk, x1,       tk    );
    if( m_digit & 1<<5 ) p->drawLine( x1,      -tk,    x1+ds,    y1+tk );
    if( m_digit & 1<<6 ) p->drawLine( x1+tk,    0,     x2-tk,    0     );
    if( m_digit & 1<<7 )
    {                               // Point
        p->setPen( Qt::NoPen );
        p->setBrush( QColor( 250, 250, 100) );
        p->drawPie( x2+ds, y2-ds, tk, tk, 0, 16*360 );
    };
    Component::paintSelected( p );
}
