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

#include <QPainter>
#include <QGraphicsProxyWidget>
#include <QToolButton>

#include "touchpad.h"
#include "simulator.h"
#include "circuit.h"
#include "itemlibrary.h"
#include "e-node.h"

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

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

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

LibraryItem* TouchPad::libraryItem()
{
    return new LibraryItem(
        tr("TouchPad (Resistive)"),
        "Peripherals",
        "touch.png",
        "TouchPadR",
        TouchPad::construct); 
}

TouchPad::TouchPad( QString type, QString id )
        : Component( type, id )
        , eElement( id )
        , m_resXA( id+"-resXA" )
        , m_resXB( id+"-resXB" )
        , m_resYA( id+"-resYA" )
        , m_resYB( id+"-resYB" )
        , m_resTouch( id+"-resTouch" )
        , m_ePinXA( id+"-ePinXA", 1 )
        , m_ePinXB( id+"-ePinXB", 1 )
        , m_ePinYA( id+"-ePinYA", 1 )
        , m_ePinYB( id+"-ePinYB", 1 )
        , m_ePinTA( id+"-ePinTA", 1 )
        , m_ePinTB( id+"-ePinTB", 1 )
{
    m_graphical = true; 

    m_eNodeX = nullptr; 
    m_eNodeY = nullptr; 

    m_RxMin = 100; 
    m_RxMax = 500; 
    m_RyMin = 100; 
    m_RyMax = 500; 

    m_transparent = false; 

    m_pin.resize(4); 
    m_vrx_p = new Pin( 270, QPoint(-12, 16+8 ), id+"-vrx_p", 0, this ); 
    m_vrx_p->setLabelText( " XP" ); 
    m_pin[0] = m_vrx_p; 

    m_vrx_m = new Pin( 270, QPoint(-4, 16+8 ), id+"-vrx_m", 0, this ); 
    m_vrx_m->setLabelText( " XM" ); 
    m_pin[1] = m_vrx_m; 

    m_vry_p = new Pin( 270, QPoint( 4, 16+8 ), id+"-vry_p", 0, this ); 
    m_vry_p->setLabelText( " Yp" ); 
    m_pin[2] = m_vry_p; 

    m_vry_m = new Pin( 270, QPoint( 12, 16+8 ), id+"-vry_m", 0, this ); 
    m_vry_m->setLabelText( " YM" ); 
    m_pin[3] = m_vry_m; 

    m_resXA.setEpin( 0, m_vrx_p ); 
    m_resXA.setEpin( 1, &m_ePinXA ); 
    m_resXB.setEpin( 1, m_vrx_m ); 
    m_resXB.setEpin( 0, &m_ePinXB ); 
    m_resYA.setEpin( 0, m_vry_p ); 
    m_resYA.setEpin( 1, &m_ePinYA ); 
    m_resYB.setEpin( 0, m_vry_m ); 
    m_resYB.setEpin( 1, &m_ePinYB ); 
    m_resTouch.setEpin( 0, &m_ePinTA ); 
    m_resTouch.setEpin( 1, &m_ePinTB ); 

    m_width  = 240; 
    m_height = 320; 

    m_proxy = Circuit::self()->addWidget( &m_touchpadW ); 
    m_proxy->setParentItem( this ); 
    updateSize(); 

    setZValue( 10 ); 
    setShowId( true ); 

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

    addPropGroup( { tr("Main"), {
        new IntProp <TouchPad>("Width", tr("Width"),"_px"
                              , this, &TouchPad::width, &TouchPad::setWidth ,0,"uint" ),

        new IntProp <TouchPad>("Height",tr("Height"),"_px"
                              , this, &TouchPad::height, &TouchPad::setHeight ,0,"uint" ),

        new BoolProp<TouchPad>("Transparent",tr("Transparent"),""
                              , this, &TouchPad::transparent, &TouchPad::setTransparent )
    }, 0} ); 

    addPropGroup( { tr("Electric"), {
        new DoubProp<TouchPad>("RxMin", tr("RxMin"),"Ω"
                              , this, &TouchPad::RxMin, &TouchPad::setRxMin,0,"uint" ),

        new DoubProp<TouchPad>("RxMax", tr("RxMax"),"Ω"
                              , this, &TouchPad::RxMax, &TouchPad::setRxMax,0,"uint" ),

        new DoubProp<TouchPad>("RyMin", tr("RyMin"),"Ω"
                              , this, &TouchPad::RyMin, &TouchPad::setRyMin,0,"uint" ),

        new DoubProp<TouchPad>("RyMax", tr("RyMax"),"Ω"
                              , this, &TouchPad::RyMax, &TouchPad::setRyMax,0,"uint" ),
    }, 0} ); 
}
TouchPad::~TouchPad(){}

void TouchPad::initialize()
{
    m_eNodeX = new eNode( m_id+"-eNodeX" ); 
    m_eNodeY = new eNode( m_id+"-eNodeY" ); 
}

void TouchPad::stamp()
{
    m_ePinXA.setEnode( m_eNodeX );   // Set eNode to internal eResistors ePins
    m_ePinXB.setEnode( m_eNodeX ); 
    m_ePinYA.setEnode( m_eNodeY ); 
    m_ePinYB.setEnode( m_eNodeY ); 
    m_ePinTA.setEnode( m_eNodeX ); 
    m_ePinTB.setEnode( m_eNodeY ); 

    m_xPos = 0; 
    m_yPos = 0; 
    m_touchpadW.resetValues(); 
    updateStep(); 
}

void TouchPad::updateStep()
{
    int xPos = m_touchpadW.getXValue(); 
    int yPos = m_touchpadW.getYValue(); 

    if( m_xPos != xPos )
    {
        m_xPos = xPos; 
        double xResA, xResB, tAdmit; 

        if( xPos < 0 )       // Not touching
        {
            xResA = xResB = (m_RxMax-m_RxMin)/2; 
            tAdmit = 0; 
        }else{
            xResA = m_RxMin + (m_RxMax-m_RxMin)*xPos/m_width; 
            xResB = m_RxMin + m_RxMax - xResA; 
            tAdmit = 1; 
        }
        m_resXA.setResistance( xResA ); 
        m_resXB.setResistance( xResB ); 
        m_resTouch.setAdmit( tAdmit ); 
        //qDebug()<<"X" << xResA<< xResB<< tAdmit; 
    }
    if( m_yPos != yPos )
    {
        m_yPos = yPos; 
        double yResA, yResB, tAdmit; 

        if( xPos < 0 )       // Not touching
        {
            yResA = yResB = (m_RyMax-m_RyMin)/2; 
            tAdmit = 0; 
        }else{
            yResA = m_RyMin + (m_RyMax-m_RyMin)*yPos/m_height; 
            yResB = m_RyMin + m_RyMax - yResA; 
            tAdmit = 1; 
        }
        m_resYA.setResistance( yResA ); 
        m_resYB.setResistance( yResB ); 
        m_resTouch.setAdmit( tAdmit ); 
        //qDebug()<<"y" << yResA<< yResB<< tAdmit; 
    }
}

void TouchPad::setWidth( int w )
{
    if( w < 40 ) w = 40; 
    m_width = w; 
    updateSize(); 
}

void TouchPad::setHeight( int h )
{
    if( h < 20 ) h = 20; 
    m_height = h; 
    updateSize(); 
}

void TouchPad::setRxMin( double min )
{
    if( min > m_RxMax ) return; 
    if( min < 1e-3 ) min = 1e-3; 
    m_RxMin = min; 
}

void TouchPad::setRxMax( double max )
{
    if( max < m_RxMin ) return; 
    m_RxMax = max; 
}

void TouchPad::setRyMin( double min )
{
    if( min > m_RyMax ) return; 
    if( min < 1e-3 ) min = 1e-3; 
    m_RyMin = min; 
}

void TouchPad::setRyMax( double max )
{
    if( max < m_RyMin ) return; 
    m_RyMax = max; 
}

void TouchPad::updateSize()
{
    m_touchpadW.setFixedSize( m_width, m_height ); 
    m_proxy->setPos( QPoint(-m_width/2, -m_height-2) ); 

    m_area = QRect(-m_width/2,-m_height, m_width, m_height+18 ); 
    setLabelPos(-35, -m_height-15, 0); 
}

void TouchPad::setTransparent( bool t )
{
    m_transparent = t; 
    m_touchpadW.setAttribute( Qt::WA_NoSystemBackground, t ); 
    update(); 
}

QPainterPath TouchPad::shape() const
{
    QPainterPath path; 
    QVector<QPointF> points; 

    points << QPointF(-m_width/2,-m_height )
           << QPointF( m_width/2,-m_height )
           << QPointF( m_width/2, 0 )
           << QPointF( 42, 0  )
           << QPointF( 42, 18 )
           << QPointF(-10, 18 )
           << QPointF(-10, 0 )
           << QPointF(-m_width/2, 0  ); 

    path.addPolygon( QPolygonF(points) ); 
    path.closeSubpath(); 
    return path; 
}

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

    p->setBrush( Qt::transparent ); 
    p->drawRoundedRect( QRect(-m_width/2,-m_height-2, m_width, m_height ), 2, 2 ); 

    if( !m_hidden ){
        p->setBrush( QColor(50, 70, 100) ); 
        p->drawRoundedRect( QRect(-20,-2, 40, 18 ), 2, 2 ); 
    }
    Component::paintSelected( p ); 
}
