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

#include <QPainter>

#include "mosfet.h"
#include "simulator.h"
#include "circuit.h"
#include "itemlibrary.h"
#include "iopin.h"

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

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

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

LibraryItem* Mosfet::libraryItem()
{
    return new LibraryItem(
        tr("Mosfet"),
        "Transistors",
        "mosfet.png",
        "Mosfet",
        Mosfet::construct); 
}

Mosfet::Mosfet( QString type, QString id )
      : Component( type, id )
      , eMosfet( id )
{
    m_area = QRectF(-12, -14, 28, 28 ); 
    setLabelPos( 18, 0, 0 ); 

    m_pin.resize(3); 
    m_ePin[0] = m_pin[0] = new Pin(  90, QPoint(8,-16), id+"-Dren", 0, this ); 
    m_ePin[1] = m_pin[1] = new Pin( 270, QPoint(8, 16), id+"-Sour", 1, this ); 
    m_ePin[2] = m_pin[2] = new IoPin( 180, QPoint(-16, 0), id+"-Gate", 0, this, input ); 
    
    Simulator::self()->addToUpdateList( this ); 

    addPropGroup( { tr("Main"), {
        new BoolProp<Mosfet>("P_Channel", tr("P Channel"),""
                                , this, &Mosfet::pChannel, &Mosfet::setPchannel ),

        new BoolProp<Mosfet>("Depletion", tr("Depletion"),""
                            , this, &Mosfet::depletion, &Mosfet::setDepletion ),
            },0} ); 

            addPropGroup( { tr("Electric"), {
        new DoubProp<Mosfet>("RDSon"    , tr("RDSon"),"Ω"
                            , this, &Mosfet::rdson, &Mosfet::setRDSon),

        new DoubProp<Mosfet>("Threshold", tr("Threshold"),"V"
                            , this, &Mosfet::threshold, &Mosfet::setThreshold )
    },0} ); 
}
Mosfet::~Mosfet(){}

void Mosfet::updateStep()
{
    if( Circuit::self()->animateCurr() ) update(); 

    if( !m_changed ) return; 
    m_changed = false; 

    updateValues(); 
    voltChanged(); 
}

void Mosfet::setPchannel( bool p )
{
    m_Pchannel = p; 
    m_changed = true; 
    update(); 
}
void Mosfet::setDepletion( bool d )
{
    m_depletion = d; 
    m_changed = true; 
    update(); 
}

void Mosfet::paint( QPainter* p, const QStyleOptionGraphicsItem* o, QWidget* w )
{
    Component::paint( p, o, w); 
    
    if( Circuit::self()->animateCurr() && m_gateV > 0 ) p->setBrush( Qt::yellow ); 
    else                                                p->setBrush( QColor( *m_backColor ) ); 

    p->drawEllipse( m_area ); 
    
    p->drawLine(-12, 0,-4, 0 ); 
    p->drawLine( -4,-8,-4, 8 ); 
    
    p->drawLine( 0,-7, 8,-7 ); 
    p->drawLine( 0, 0, 8, 0 ); 
    p->drawLine( 0, 7, 8, 7 ); 
    
    p->drawLine( 8,-12, 8,-7 ); 
    p->drawLine( 8, 12, 8, 0 ); 
    
    p->setBrush( QColor( *m_foreColor ) ); 
    if( m_Pchannel )
    {
        QPointF points[3] = {
        QPointF( 7, 0 ),
        QPointF( 3,-2 ),
        QPointF( 3, 2 ) }; 
        p->drawPolygon( points, 3 ); 
    } else {
        QPointF points[3] = {
        QPointF( 1, 0 ),
        QPointF( 5,-2 ),
        QPointF( 5, 2 )     }; 
        p->drawPolygon( points, 3 ); 
    }
    if( m_depletion )
    {
        QPen pen(Qt::black, 2.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); 
        p->setPen( pen ); 
        p->drawLine( 0,-9, 0, 9 ); 
    } else {
        p->drawLine( 0,-9, 0,-5 ); 
        p->drawLine( 0,-2, 0, 2 ); 
        p->drawLine( 0, 5, 0, 9 ); 
    }
    Component::paintSelected( p ); 
}
