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

#include <QPainter>

#include "ledrgb.h"
#include "connector.h"
#include "circuit.h"
#include "simulator.h"
#include "itemlibrary.h"
#include "circuitwidget.h"
#include "pin.h"

#include "boolprop.h"
#include "doubleprop.h"

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

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

LibraryItem* LedRgb::libraryItem()
{
    return new LibraryItem(
        tr("Led Rgb"),
        "Leds",
        "ledrgb.png",
        "LedRgb",
        LedRgb::construct); 
}

LedRgb::LedRgb( QString type, QString id )
      : Component( type, id )
      , eElement( id )
{
    m_graphical = true; 
    m_color = QColor(0,0,0); 
    bright[0] = 15; 
    bright[1] = 15; 
    bright[2] = 15; 

    setComCathode( true ); 

    m_pin.resize( 4 ); 
    for( int i=0;  i<3;  ++i )
    {
        m_pin[i] = new Pin( 180, QPoint(-16, -8+8*i ), m_id+"-Pin"+QString::number(i), 0, this); 
        m_pin[i]->setColor( QColor(180*(i==0),120*(i==1),160*(i==2)) ); 
    }
    m_pin[3] = new Pin( 0, QPoint( 16, 0 ), m_id+"-Pin"+QString::number(3), 0, this); 

    for( int i=0;  i<3;  ++i )
    {
        QString ledId = id+"_Led"+QString::number(i); 
        m_led[i] = new eLed( ledId ); 
        m_led[i]->setEpin( 0, new ePin( ledId+"-ePin"+QString::number(0), 0 ) ); 
        m_led[i]->setEpin( 1, new ePin( ledId+"-ePin"+QString::number(1), 1 ) ); 
        if( i > 0 ) m_led[i]->setThreshold( 3.5 ); 
    }
    Simulator::self()->addToUpdateList( this ); 

    addPropGroup( { tr("Electric"), {
        new BoolProp<LedRgb>("CommonCathode", tr("Common Cathode"), ""
                            , this, &LedRgb::isComCathode, &LedRgb::setComCathode, propNoCopy),

        new ComProperty("", tr("Red:"),"","",0),

        new DoubProp<LedRgb>("Threshold_R" , tr("Forward Voltage"), "V"
                            , this, &LedRgb::threshold_R, &LedRgb::setThreshold_R ),

        new DoubProp<LedRgb>("MaxCurrent_R", tr("Max Current"), "mA"
                                , this, &LedRgb::maxCurrent_R, &LedRgb::setMaxCurrent_R ),

        new DoubProp<LedRgb>("Resistance_R", tr("Resistance"), "Ω"
                            , this, &LedRgb::res_R, &LedRgb::setRes_R ),

        new ComProperty("", tr("Green:"),"","",0),

        new DoubProp<LedRgb>("Threshold_G" , tr("Forward Voltage"), "V"
                            , this, &LedRgb::threshold_G, &LedRgb::setThreshold_G ),

        new DoubProp<LedRgb>("MaxCurrent_G", tr("Max Current"), "mA"
                                , this, &LedRgb::maxCurrent_G, &LedRgb::setMaxCurrent_G ),

        new DoubProp<LedRgb>("Resistance_G", tr("Resistance"), "Ω"
                            , this, &LedRgb::res_G, &LedRgb::setRes_G ),

        new ComProperty("", tr("Blue:"),"","",0),

        new DoubProp<LedRgb>("Threshold_B" , tr("Forward Voltage"),"V"
                            , this, &LedRgb::threshold_B, &LedRgb::setThreshold_B ),

        new DoubProp<LedRgb>("MaxCurrent_B", tr("Max Current"),"mA"
                            , this, &LedRgb::maxCurrent_B, &LedRgb::setMaxCurrent_B ),

        new DoubProp<LedRgb>("Resistance_B", tr("Resistance"),"Ω"
                            , this, &LedRgb::res_B, &LedRgb::setRes_B )
    }, 0} ); 
}
LedRgb::~LedRgb(){}

void LedRgb::stamp()
{
    eNode* comEnode = m_pin[3]->getEnode(); 
    for( int i=0;  i<3;  ++i )
    {
        eNode* node = m_pin[i]->getEnode(); 
        eLed* led   = m_led[i]; 

        if( m_commonCathode ){
            led->getEpin(0)->setEnode( node ); 
            led->getEpin(1)->setEnode( comEnode ); 
        }else{
            led->getEpin(1)->setEnode( node ); 
            led->getEpin(0)->setEnode( comEnode ); 
}   }   }

void LedRgb::updateStep()
{
    m_warning = false; 
    m_crashed = false; 
    bool updt = false; 

    for( int i=0;  i<3;  ++i )
    {
        double brg = m_led[i]->brightness()*255+15; 
        m_led[i]->updateBright(); 
        m_warning |= m_led[i]->overCurrent() > 1.5; 
        m_crashed |= m_led[i]->overCurrent() > 2; 
        bright[i] = m_led[i]->brightness()*255+15; 
        if( bright[i] > 255 ) bright[i] = 255; 
        updt |= (brg != bright[i]) | m_warning; 
    }
    if( updt ) update(); 
}

void LedRgb::setComCathode( bool cat )
{
    if( Simulator::self()->isRunning() ) CircuitWidget::self()->powerCircOff(); 
    m_commonCathode = cat; 
    if( cat ) m_area = QRect(-8, -10, 20, 20 ); 
    else      m_area = QRect(-12, -10, 20, 20 ); 

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

void LedRgb::setThreshold_R( double threshold )
{ 
    if( threshold < 1e-6 ) threshold = 1e-6; 
    m_led[0]->setThreshold( threshold ); 
}

void LedRgb::setMaxCurrent_R( double current )
{
    if( current < 1e-6 ) current = 1e-6; 
    m_led[0]->setMaxCurrent( current ); 
}

void LedRgb::setRes_R( double resist )
{
    if( resist == 0 ) resist = 1e-14; 
    m_led[0]->setResistance( resist ); 
}

void LedRgb::setThreshold_G( double threshold )
{
    if( threshold < 1e-6 ) threshold = 1e-6; 
    m_led[1]->setThreshold( threshold ); 
}

void LedRgb::setMaxCurrent_G( double current )
{
    if( current < 1e-6 ) current = 1e-6; 
    m_led[1]->setMaxCurrent( current ); 
}

void LedRgb::setRes_G( double resist )
{
    if( resist == 0 ) resist = 1e-14; 
    m_led[1]->setResistance( resist ); 
}

void LedRgb::setThreshold_B( double threshold )
{
    if( threshold < 1e-6 ) threshold = 1e-6; 
    m_led[2]->setThreshold( threshold ); 
}

void LedRgb::setMaxCurrent_B( double current )
{
    if( current < 1e-6 ) current = 1e-6; 
    m_led[2]->setMaxCurrent( current ); 
}

void LedRgb::setRes_B( double resist )
{
    if( resist == 0 ) resist = 1e-14; 
    m_led[2]->setResistance( resist ); 
}

void LedRgb::setHidden( bool hid, bool hidArea, bool hidLabel )
{
    Component::setHidden( hid, hidArea, hidLabel ); 
    if( hid ) m_area = QRect(-10,-10, 20, 20 ); 
    else{
        if( m_commonCathode ) m_area = QRect( -8,-10, 20, 20 ); 
        else                  m_area = QRect(-12,-10, 20, 20 ); 
    }
}

void LedRgb::paint( QPainter* p, const QStyleOptionGraphicsItem* o, QWidget* w )
{
    Component::paint( p, o, w ); 

    QPen pen(Qt::black, 4, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); 
    QColor color; 

    if( m_warning ) // Led overcurrent
    {
        p->setBrush( QColor( 255, 150, 0 ) ); 
        color = QColor( Qt::red ); 
        pen.setColor( color ); 
    }
    if( m_crashed )  // Led extreme overcurrent
    {
        p->setBrush( Qt::white ); 
        color = QColor( Qt::white ); 
        pen.setColor( color ); 
    }else{
        color = QColor( bright[0], bright[1], bright[2] ); 
    }
    p->setPen( pen ); 
    p->drawRoundedRect( m_area, 2, 2 ); 

    pen.setColor( color ); 
    pen.setWidth( 2 ); 
    p->setPen( pen ); 
    p->setBrush( color ); 
    p->drawEllipse( m_area ); 

    Component::paintSelected( p ); 
}
