/***************************************************************************
 *   Copyright (C) 2020 by Benoit ZERR                                     *
 *                                                                         *
 ***( see copyright.txt file at root folder )*******************************/

/*   Modified 2020 by Santiago González                                    *
 *   santigoro@gmail.com                                                   *
 *                                                                         */

#include <QPainter>
#include <iostream>

#include "strain.h"
#include "connector.h"
#include "circuit.h"
#include "itemlibrary.h"

#include "doubleprop.h"
#include "propdialog.h"

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

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

LibraryItem* Strain::libraryItem()
{
    return new LibraryItem(
        tr("Force Strain Gauge"),
        "Resistive Sensors",
        "strain.png",
        "Strain",
        Strain::construct ); 
}

Strain::Strain( QString type, QString id )
      : VarResBase( type, id )
{
    m_area = QRectF(-12,-20, 24, 24 ); 
    Dialed::m_areaComp = m_area; 

    VarResBase::setVal( 0 ); 

    addPropGroup( { tr("Main"), {
        new DoubProp<Strain>("Force_N", tr("Current Value"), "N"
                            , this, &Strain::getVal, &Strain::setVal ),

        new DoubProp<Strain>("Min_Force_N", tr("Minimum Value"), "N"
                            , this, &Strain::minVal,  &Strain::setMinVal ),

        new DoubProp<Strain>("Max_Force_N", tr("Maximum Value"), "N"
                            , this, &Strain::maxVal, &Strain::setMaxVal ),

        new DoubProp<Strain>("Dial_Step", tr("Dial Step"), "N"
                            , this, &Strain::getStep, &Strain::setStep )
    }, 0} ); 

    addPropGroup( { tr("Parameters"), {
        new DoubProp<Strain>("Ref_Temp", tr("Ref. Temperature"), "ºC"
                            , this, &Strain::refTemp, &Strain::setRefTemp ),

        new DoubProp<Strain>("Temp", tr("Temperature"), "ºC"
                            , this, &Strain::getTemp, &Strain::setTemp )
    }, 0} ); 
    addPropGroup( { tr("Dial"), Dialed::dialProps(), groupNoCopy } ); 
}
Strain::~Strain() { }

void Strain::initialize()
{
  //m_last_step =  Simulator::self()->step(); 
  //m_resist = sensorFunction (m_sense); 
  m_last_resist = 1/m_admit; 
  m_new_resist = m_last_resist; 

  //setResist ( m_resist); 
  updateStep (); 
}

void Strain::updateStep()
{
    if( !m_needUpdate ) return; 
    m_needUpdate = false; 

    /*m_step = Simulator::self()->step(); 
    double t = (double) m_step/1e6; 
    double dt = t - m_t0_tau; 

    m_new_resist = sensorFunction (m_sense); 
    double dr = m_new_resist - m_last_resist; 
    m_resist = m_last_resist + dr * (1.0 -exp(-dt/m_tau)); 
    
    setUnit (" "); 
    setResist ( m_resist); */

    //qDebug() << "Strain::Strain" << m_res.res() << m_res.current()
    //	     << m_ePinTst1->isConnected() << m_ePinTst2->isConnected() ; 
    //m_last_step = m_step; 

    double res = sensorFunction( m_value ); 
    eResistor::setResistance( res ); 

    if( m_propDialog ) m_propDialog->updtValues(); 
    else setValLabelText( getPropStr( showProp() ) ); 
}

/*void Strain::senseChanged( int val ) // Called when dial is rotated
{
    //qDebug() <<"Strain::senseChanged" << val; 
    //double sense = (double)(m_dial->value()); 
    //sense = round(sense/(double)m_sense_step)*(double)m_sense_step; 
    //qDebug()<<"Strain::senseChanged dialValue sense"<<m_dial->value()<<sense; 
    //setSense( sense ); 
    //m_dialW.dial->setValue(m_sense); 
    //m_t0_tau = (double) (Simulator::self()->step())/1e6; 
    //m_last_resist = m_resist; 
}*/


double Strain::sensorFunction( double forceN )
{
  double resistance; 

  m_delta_r = m_drPrecalc*forceN; 

  resistance = m_r0 + m_delta_r + m_delta_r_t; 
  return resistance; 
}

void Strain::updateParameters()
{
    m_k_long = 1+2.0*m_coef_poisson+m_cste_bridgman*(1-2*m_coef_poisson); 
    //qDebug() << "K = " << m_k_long; 
    m_k = m_k_long * (1 - m_coef_transverse); 
    m_section_body = m_h_body * m_w_body; 
    m_delta_r_t = (m_alpha_r+m_k*(m_lambda_s - m_lambda_j)) * (m_temp - m_ref_temp) * m_r0; 
    m_drPrecalc = m_r0*m_k/(m_young_modulus*m_section_body); 
}

void Strain::setRefTemp( double t )
{
    m_ref_temp = t; 
    updateParameters(); 
}

void Strain::setTemp( double t)
{
    m_temp= t; 
    updateParameters(); 
}

void Strain::paint( QPainter* p, const QStyleOptionGraphicsItem* o, QWidget* w )
{
    if( m_hidden ) return; 

    Component::paint( p, o, w ); 
    p->drawRect(-11,-20, 22, 24 ); 
    p->fillRect(-8,-2, 4, 4, Qt::black ); 
    p->fillRect( 8,-2,-4, 4, Qt::black ); 

    QPen pen(Qt::black, 1.5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); 
    p->setPen( pen ); 

    const QPointF points[8] = {
        QPointF(-6, 0 ),
        QPointF(-6,-16 ),
        QPointF(-2,-16 ),
        QPointF(-2,-4 ),
        QPointF( 2,-4 ),
        QPointF( 2,-16 ),
        QPointF( 6,-16 ),
        QPointF( 6, 0 ), }; 

    p->drawPolyline( points, 8 ); 

    Component::paintSelected( p ); 
}
