//**************************************************************************************************
//                                          NbkGnuCap.cpp                                          *
//                                         ---------------                                         *
// Started     : 2003-09-05                                                                        *
// Last Update : 2018-10-03                                                                        *
// Copyright   : (C) 2003-2018 MSWaters                                                            *
//**************************************************************************************************

//**************************************************************************************************
//                                                                                                 *
//      This program is free software; you can redistribute it and/or modify it under the          *
//      terms of the GNU General Public License as published by the Free Software Foundation;      *
//      either version 3 of the License, or (at your option) any later version.                    *
//                                                                                                 *
//**************************************************************************************************

#include "NbkGnuCap.hpp"

//**************************************************************************************************
// Implement an event table.

wxBEGIN_EVENT_TABLE( NbkGnuCap, NbkSimEngBase )

  EVT_NOTEBOOK_PAGE_CHANGED( -1,          NbkGnuCap::OnPageChangd )

  EVT_BUTTON( PnlAnaBase::ID_BTN_OPTIONS, NbkGnuCap::OnBtnOptions )

wxEND_EVENT_TABLE( )

//**************************************************************************************************
// Constructor.
//
// Arguments:
//   poParent - The parent window
//   oWinID   - The display object ID
//   roPosn   - The notebook position
//   roSize   - The notebook size

NbkGnuCap::NbkGnuCap( wxWindow * poParent, wxWindowID oWinID )
                    : NbkSimEngBase( poParent, oWinID ), m_oDlgCfgOPT( poParent )
{
  // Set the simulator engine type specifier
  m_eSimEng = eSIMR_GNUCAP;

  // Create the various display objects
  m_poPnlGnuCapOP = new PnlGnuCapOP( this );
  m_poPnlGnuCapDC = new PnlGnuCapDC( this );
  m_poPnlGnuCapAC = new PnlGnuCapAC( this );
  m_poPnlGnuCapTR = new PnlGnuCapTR( this );
//  m_poPnlGnuCapFO = new PnlGnuCapFO( this );

  // Add the display objects to the note book
  AddPage( m_poPnlGnuCapOP, wxT( " Quiescent  "     ) );
  AddPage( m_poPnlGnuCapDC, wxT( "       DC       " ) );
  AddPage( m_poPnlGnuCapAC, wxT( "       AC       " ) );
  AddPage( m_poPnlGnuCapTR, wxT( "  Transient  "    ) );
//  AddPage( m_poPnlGnuCapFO, wxT( "   Fourier    "   ) );

  // Specify the default page to be displayed
  SetSelection( 0 );
}

//**************************************************************************************************
// Destructor.

NbkGnuCap::~NbkGnuCap( )
{
}

//**************************************************************************************************
// Clear the object attributes.
//
// Return Values:
//   true  - Success
//   false - Failure

bool  NbkGnuCap::bClear( void )
{
  bool  bRtn=true;

  // Clear the base class
  if( ! NbkSimEngBase  ::bClear( ) ) bRtn = false;

  if( ! m_poPnlGnuCapOP->bClear( ) ) bRtn = false;
  if( ! m_poPnlGnuCapDC->bClear( ) ) bRtn = false;
  if( ! m_poPnlGnuCapAC->bClear( ) ) bRtn = false;
  if( ! m_poPnlGnuCapTR->bClear( ) ) bRtn = false;
//if( ! m_poPnlGnuCapFO->bClear( ) ) bRtn = false;

  if( ! m_oDlgCfgOPT    .bClear( ) ) bRtn = false;

  return( bRtn );
}

//**************************************************************************************************
// Load information from a simulation object.
//
// Argument List:
//   roSimn - The simulation object
//
// Return Values:
//   true  - Success
//   false - Failure

bool  NbkGnuCap::bLoad( const SimnBase & roSimn )
{
  bool    bRtn=true;
  size_t  sz1;

  if( roSimn.eGetSimEng( ) != eSIMR_GNUCAP )             return( false );

  SimnGnuCap & roSimnGcp = (SimnGnuCap &) roSimn;

  if( ! bSetPage( roSimnGcp.eGetAnaType( ) ) )           bRtn = false;

  sz1 = 0;
  if( m_poPnlGnuCapOP->bLoad( roSimnGcp ) ) sz1++;
  if( m_poPnlGnuCapDC->bLoad( roSimnGcp ) ) sz1++;
  if( m_poPnlGnuCapAC->bLoad( roSimnGcp ) ) sz1++;
  if( m_poPnlGnuCapTR->bLoad( roSimnGcp ) ) sz1++;
//if( m_poPnlGnuCapFO->bLoad( roSimnGcp ) ) sz1++;
  if( sz1 == 0 )                                         bRtn = false;

  if( ! m_oDlgCfgOPT.bSetValues( roSimnGcp.m_oCmdOPT ) ) bRtn = false;

  return( bRtn );
}

//**************************************************************************************************
// Save information to a simulation object.
//
// Argument List:
//   roSimn - The simulation object
//
// Return Values:
//   true  - Success
//   false - Failure

bool  NbkGnuCap::bSave( SimnBase & roSimn )
{
  wxString  os1;

  // Only proceed if this is an GNU-Cap simulation object
  if( roSimn.eGetSimEng( ) != eSIMR_GNUCAP ) return( false );

  SimnGnuCap & roSimnGcp = (SimnGnuCap &) roSimn;

  // Clear the error string
  NbkSimEngBase::m_osErrMsg.Empty( );

  // Create the analysis command/s
  switch( GetSelection( ) )
  {
    case 0 : // OP analysis
      if( m_poPnlGnuCapOP->bSave( roSimnGcp ) )
           os1.Empty( );
      else SetErrMsg( m_poPnlGnuCapOP->rosGetErrMsg( ) );
      break;

    case 1 : // DC analysis
      if( m_poPnlGnuCapDC->bSave( roSimnGcp ) )
           os1 = roSimnGcp.m_oCmdDC.m_osTempC;
      else SetErrMsg( m_poPnlGnuCapDC->rosGetErrMsg( ) );
      break;

    case 2 : // AC analysis
      if( m_poPnlGnuCapAC->bSave( roSimnGcp ) )
           os1 = roSimnGcp.m_oCmdAC.m_osTempC;
      else SetErrMsg( m_poPnlGnuCapAC->rosGetErrMsg( ) );
      break;

    case 3 : // TR analysis
      if( m_poPnlGnuCapTR->bSave( roSimnGcp ) )
           os1 = roSimnGcp.m_oCmdTR.m_osTempC;
      else SetErrMsg( m_poPnlGnuCapTR->rosGetErrMsg( ) );
      break;

//    case 4 : // FO analysis
//      if( m_poPnlGnuCapFO->bSave( roSimnGcp ) )
//           os1 = roSimnGcp.m_oCmdFO.m_osTempC;
//      else SetErrMsg( m_poPnlGnuCapFO->rosGetErrMsg( ) );
//      break;

    default:                                 return( false );
  }
  if( ! bIsOk( ) )                           return( false );

  // Create the OPTIONS command
  m_oDlgCfgOPT.bGetValues( roSimnGcp.m_oCmdOPT );
  if( ! os1.IsEmpty( ) ) roSimnGcp.m_oCmdOPT.m_osTEMP = os1;
  roSimnGcp.m_oCmdOPT.bFormat( );
  if( ! roSimnGcp.m_oCmdOPT.bIsValid( ) )
  {
    os1 = wxT("OPTIONS command fault :\n\n  ");
    SetErrMsg( os1 + roSimnGcp.m_oCmdOPT.rosGetErrMsg( ) );
    return( false );
  }

  return( true );
}

//**************************************************************************************************
// Set the page to be displayed.
//
// Argument List:
//   eCmdType - The enumerated analysis type specifier
//
// Return Values:
//   true  - Success
//   false - Failure

bool  NbkGnuCap::bSetPage( eTypeCmd eAnalysis )
{
  int  iPage;

  switch( eAnalysis )
  {
    case eCMD_OP   : iPage = 0; break;
    case eCMD_DC   : iPage = 1; break;
    case eCMD_AC   : iPage = 2; break;
    case eCMD_TR   : iPage = 3; break;
//    case eCMD_FO   : iPage = 4; break;
    default        : return( false );
  }

  SetSelection( iPage ); // Specify the page to be displayed

  return( true );
}

//**************************************************************************************************
// Set the page to be displayed.
//
// Argument List:
//   rosAnalysis - The two letter analysis type specifier (case ignored)
//
// Return Values:
//   true  - Success
//   false - Failure

bool  NbkGnuCap::bSetPage( const wxString & rosAnalysis )
{
  eTypeCmd  eAnalysis=eCMD_NONE;
  wxString  os1;

  os1 = rosAnalysis.Upper( );

  if( os1.Length( ) == 2 )
  {
    if(      os1 == wxT("OP") ) eAnalysis = eCMD_OP;
    else if( os1 == wxT("DC") ) eAnalysis = eCMD_DC;
    else if( os1 == wxT("AC") ) eAnalysis = eCMD_AC;
    else if( os1 == wxT("TR") ) eAnalysis = eCMD_TR;
//    else if( os1 == wxT("FO") ) eAnalysis = eCMD_FO;
//    else if( os1 == wxT("DI") ) eAnalysis = eCMD_DI;
//    else if( os1 == wxT("NO") ) eAnalysis = eCMD_NO;
//    else if( os1 == wxT("PZ") ) eAnalysis = eCMD_PZ;
//    else if( os1 == wxT("SE") ) eAnalysis = eCMD_SE;
//    else if( os1 == wxT("TF") ) eAnalysis = eCMD_TF;
  }

  return( bSetPage( eAnalysis ) );
}

//**************************************************************************************************
// Get the two letter page specifier.
//
// Return Values:
//   Success - The two letter analysis type specifier (lower case)
//   Failure - An empty string

const wxString & NbkGnuCap::rosGetPage( void )
{
  static  wxString  osAnalysis;

  switch( eGetPage( ) )
  {
    case eCMD_OP : osAnalysis = wxT("op"); break;
    case eCMD_DC : osAnalysis = wxT("dc"); break;
    case eCMD_AC : osAnalysis = wxT("ac"); break;
    case eCMD_TR : osAnalysis = wxT("tr"); break;
//    case eCMD_FO : osAnalysis = wxT("fo"); break;
    default      : osAnalysis.Empty( );
  }

  return( osAnalysis );
}

//**************************************************************************************************
// Get the enumerated page specifier.
//
// Return Values:
//   Success - The enumerated analysis specifier
//   Failure - eCMD_NONE

eTypeCmd  NbkGnuCap::eGetPage( void )
{
  eTypeCmd  eAnalysis;

  switch( GetSelection( ) )
  {
    case  0 : eAnalysis = eCMD_OP; break;
    case  1 : eAnalysis = eCMD_DC; break;
    case  2 : eAnalysis = eCMD_AC; break;
    case  3 : eAnalysis = eCMD_TR; break;
//    case  4 : eAnalysis = eCMD_FO; break;
    default : eAnalysis = eCMD_NONE;
  }

  return( eAnalysis );
}

//**************************************************************************************************
//                                         Event Handlers                                          *
//**************************************************************************************************
// This event is generated when a notebook page has just changed.
//
// Argument List:
//   roEvtNbk - An object holding information about the event

void  NbkGnuCap::OnPageChangd( wxNotebookEvent & roEvtNbk )
{
  PnlAnaBase * poPnlOld=NULL;
  PnlAnaBase * poPnlNew=NULL;
  wxString     os1;
  int          i1;

  // Get pointers to the old and new (current) analysis panels
  i1 = roEvtNbk.GetOldSelection( );
  if( i1 != wxNOT_FOUND ) poPnlOld = static_cast<PnlAnaBase *>( GetPage( (size_t) i1 ) );
  poPnlNew = static_cast<PnlAnaBase *>( GetCurrentPage( ) );

  // Synchronize the ambient temperature values between the different analysis pages
  if( g_oConfig.bGetSyncTemps( ) )
  {
    // Transfer the ambient temperature from the previous page to the OPTIONS dialog
    if( poPnlOld != NULL )
    {
      if( poPnlOld->m_oPnlTemp.GetParent( ) != NULL )
      {
        os1 = poPnlOld->m_oPnlTemp.rosGetValue( );
        m_oDlgCfgOPT.bSetValue( DlgGnuCapCfgOPT::ID_PNL_TEMP, os1 );
      }
    }

    // Transfer the ambient temperature from the OPTIONS dialog to current page
    if( poPnlNew->m_oPnlTemp.GetParent( ) != NULL )
    {
      os1 = m_oDlgCfgOPT.rosGetValue( DlgGnuCapCfgOPT::ID_PNL_TEMP );
      poPnlNew->m_oPnlTemp.bSetValue( os1 );
    }
  }

  // Record the signal source value from the old panel
  if( poPnlOld != NULL )
  {
    if( poPnlOld->m_oChoSrcName.GetSelection( ) > 0 )
    {
      m_oCpntSigSrc.bSetName( poPnlOld->m_oChoSrcName.GetStringSelection( ) );
      if( poPnlOld->m_oPnlSrcLvl.GetParent( ) != NULL )
      {
        os1 = poPnlOld->m_oPnlSrcLvl.rosGetValue( );
        m_oCpntSigSrc.bSetValue( os1 );
      }
      else if( poPnlOld->eGetAnalysType( ) == eCMD_TR )
      {
        os1 = m_poPnlGnuCapTR->m_oDlgCfgGEN.rosGetValue( DlgGnuCapCfgGEN::ID_PNL_AMPLITUDE );
        m_oCpntSigSrc.bSetValue( os1 );
      }
    }
    else m_oCpntSigSrc.bClear( );
  }

  // Synchronize the signal sources between the different analysis pages
  if( g_oConfig.bGetSyncSigSrcs( ) )
  {
      os1 = m_oCpntSigSrc.rosGetName( );

    if( poPnlNew->m_oChoSrcName.SetStringSelection( os1 ) )
    { // Set the signal source value if it's been defined
      if( poPnlNew->m_oPnlSrcLvl.GetParent( ) != NULL )
      {
        poPnlNew->m_oPnlSrcLvl.bSetUnitsType( m_oCpntSigSrc.eGetUnitsType( ) );
        poPnlNew->m_oPnlSrcLvl.bSetValue( m_oCpntSigSrc.rosGetValue( ) );
      }
      else if( poPnlNew->eGetAnalysType( ) == eCMD_TR )
      {
        poPnlNew->m_oPnlSrcLvl.bSetUnitsType( m_oCpntSigSrc.eGetUnitsType( ) );
        os1 = m_oCpntSigSrc.rosGetValue( );
        m_poPnlGnuCapTR->m_oDlgCfgGEN.bSetValue( DlgGnuCapCfgGEN::ID_PNL_AMPLITUDE, os1 );
      }
    }
    else
    { // Couldn't set the signal source name so clear it
      poPnlNew->m_oChoSrcName.SetSelection( 0 );
      if( poPnlNew->m_oPnlSrcLvl.GetParent( ) != NULL )
      {
        poPnlNew->m_oPnlSrcLvl.bSetUnitsType( eUNITS_NONE );
        poPnlNew->m_oPnlSrcLvl.bSetValue( 0.0 );
      }
    }

    // Update the signal parameter units
    if( poPnlNew->eGetAnalysType( ) == eCMD_DC )
      m_poPnlGnuCapDC->OnSrcName( (wxCommandEvent &) roEvtNbk );
  }

  // Allow additional event handlers to be called
  roEvtNbk.Skip( );
}

//**************************************************************************************************
// Setup .OPTIONS command button event handler.
//
// Argument List:
//   roEvtCmd - An object holding information about the event

void  NbkGnuCap::OnBtnOptions( wxCommandEvent & roEvtCmd )
{
  PnlAnaBase * poPnlAna;
  wxString     os1;
  int          i1;

  // Get a pointer to the currently displayed analysis page
  poPnlAna = static_cast<PnlAnaBase *>( GetCurrentPage( ) );
  if( poPnlAna == NULL ) return;

  // Set the temperature in the OPTIONS dialog
  if( poPnlAna->m_oPnlTemp.GetParent( ) != NULL )
  {
    os1 = poPnlAna->m_oPnlTemp.rosGetValue( );
    m_oDlgCfgOPT.bSetValue( DlgGnuCapCfgOPT::ID_PNL_TEMP, os1 );
  }

  // Display the OPTIONS dialog
  m_oDlgCfgOPT.CenterOnParent( );
  i1 = m_oDlgCfgOPT.ShowModal( );
  if( i1 != wxID_OK )    return;

  // Set the temperature in the analysis panel
  if( poPnlAna->m_oPnlTemp.GetParent( ) != NULL )
  {
    os1 = m_oDlgCfgOPT.rosGetValue( DlgGnuCapCfgOPT::ID_PNL_TEMP );
    poPnlAna->m_oPnlTemp.bSetValue( os1 );
  }
}

//**************************************************************************************************
