//**************************************************************************************************
//                                          PrcGWave.cpp                                           *
//                                         --------------                                          *
// Started     : 2004-03-29                                                                        *
// Last Update : 2016-10-23                                                                        *
// Copyright   : (C) 2004-2016 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 "PrcGWave.hpp"

//**************************************************************************************************
// Constructor.

PrcGWave::PrcGWave( void ) : PrcBase( wxPROCESS_REDIRECT )
{
  // Initialize the object attributes
  m_oNameResults.Clear( );
  m_oNameLog    .Clear( );

  // Attempt to set and find the gWave binary
  bSetBinFile( BIN_GWAVE );
}

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

PrcGWave::~PrcGWave( )
{
}

//**************************************************************************************************
// Set the simulation results file name.
//
// Argument List:
//   psFileName - a string containing the full path and file name
//
// Return Values:
//   true  - Success
//   false - Failure

bool  PrcGWave::bSetResultsFile( const wxString & rosFileName )
{
  wxFileName  ofn1;

  ofn1 = rosFileName;
  if( ofn1.GetPath( ).IsEmpty( ) ) ofn1.SetPath( wxT(".") );

  if( ! ofn1.IsOk( )       ) return( false );
  if( ! ofn1.FileExists( ) ) return( false );

  m_oNameResults = ofn1;

  return( true );
}

//**************************************************************************************************
// Filter the results file so that the data viewer utility is happy with it.
//
// There are several things that a data viewer can object to :
//  - gwave doesn't like the GNU-Cap banner at the start to the results file, so it's removed here.
//  - gwave doesn't like error messages interspersed with the lines of data, so they are removed
//    here.
//  - For good measure lines and fields are also formatted.
//
// Return Values:
//   true  - Success
//   false - Failure

bool  PrcGWave::bFilterFile( void )
{
  wxString  os1;
  size_t    sz1, sz2;
  wxChar    oc1;
  bool      bRtn=true;

  // Attempt to open the results file
  wxTextFile  oFileCct( m_oNameResults.GetFullPath( ) );
  if( ! oFileCct.Exists( ) ) return( false );
  if( ! oFileCct.Open( ) )   return( false );

  // Has this file been formatted already?
  if( oFileCct.GetFirstLine( ).GetChar( 0 ) == wxT('#') ) return( true );

  // Find the beginning of the data area (ie. the last line beginning with '#')
  for( sz1=sz2=0; sz1<oFileCct.GetLineCount( ); sz1++ )
  {
    os1 = oFileCct.GetLine( sz1 );
    if( ! os1.IsEmpty( ) )
      if( os1.GetChar( 0 ) == wxT('#') )
        sz2 = sz1;
  }

  // Delete the banner
  for( sz1=0; sz1<sz2; sz1++ ) oFileCct.RemoveLine( 0 );
  if( oFileCct.GetLineCount( ) <= 1 )                     return( false );

  // Delete any simulator error messages eg. "open circuit: internal node 3"
  // (All lines should start with a digit except for the first)
  for( sz1=1; !oFileCct.Eof( ) && sz1<oFileCct.GetLineCount( ); sz1++ )
  {
    os1 = oFileCct.GetLine( sz1 );
    if( os1.Length( ) <= 1 )
    { // Delete empty lines
      oFileCct.RemoveLine( sz1 );
      sz1--;
      continue;
    }
    oc1 = os1.GetChar( 1 );
    if( ! wxIsdigit( oc1 ) )
    { // Delete non-data lines
      oFileCct.RemoveLine( sz1 );
      sz1--;
      continue;
    }
  }

  // Format each data line in the file
//  for( szt1=1; szt1<oFileCct.GetLineCount( ); szt1++ )
//    if( ! bFormatLine( oFileCct.GetLine( szt1 ) ) )
//      bRtn = false;

  oFileCct.Write( ); // Save the changes to disk
  oFileCct.Close( ); // Close the file

  return( bRtn );
}

//**************************************************************************************************
// Reformat the lines from the results file.
//
// Argument List:
//   rosLine - The line to be formatted
//
// Return Values:
//   true  - Success
//   false - Failure
/*
bool  PrcGWave::bFormatLine( wxString & rosLine )
{
  wxStringTokenizer  ostk1;
  wxString  os1, os2;

  // Check for an empty string
  if( rosLine.IsEmpty( ) )         return( false );

  // Break the line into fields
  ostk1.SetString( rosLine );
  if( ostk1.CountTokens( ) < 2 ) return( false );

  // Reformat the line
  while( ostk1.HasMoreTokens( ) )
  {
    os1 = ostk1.GetNextToken( );
    if( ! bFormatField( os1 ) )    return( false );
    if( os2.IsEmpty( ) ) os2 = os1;
    else                 os2 << wxT("     ") << os1;
  }

  rosLine = os2;

  return( true );
}
*/
//**************************************************************************************************
// Reformat the fields from the results file.
//
// Argument List:
//   rosField - The field to be formatted
//
// Return Values:
//   true  - Success
//   false - Failure
/*
bool  PrcGWave::bFormatField( wxString & rosField )
{
  wxString  os1;
  wxChar    oc1;
  size_t    szt1;

  // Check for an empty string
  if( rosField.IsEmpty( ) ) return( false );

  // Extract the value and the units
  oc1 = 0;
  for( szt1=0; szt1<rosField.Length( ); szt1++ )
  {
    oc1 = rosField.GetChar( szt1 );
    if( oc1!=wxT('-') && !wxIsdigit( oc1 ) && oc1!=wxT('.') ) break;
    else oc1 = 0;
  }
  os1 = rosField.Left( szt1 );

  // Reformat the field
  switch( oc1 )
  {
    case wxT('M'): os1 << wxT("E+06"); break;
    case wxT('K'): os1 << wxT("E+03"); break;
    case wxT('m'): os1 << wxT("E-03"); break;
    case wxT('u'): os1 << wxT("E-06"); break;
    case wxT('n'): os1 << wxT("E-09"); break;
    case wxT('p'): os1 << wxT("E-12"); break;
    case 0: break;
    default : return( false );
  }

  rosField = os1;

  return( true );
}
*/
//**************************************************************************************************
// View the results of a simulation.
//
// (Eg. using the following: gwave ../sch/test-amp1.gnucap.dc)
//
// Return Values:
//   true  - Success
//   false - Failure

bool  PrcGWave::bExec( void )
{
  wxString  os1;

  // Test file names needed by this function
  if( ! bBinExists( ) )                               return( false );
  if( !m_oNameResults.FileExists( ) || !m_oNameResults.IsOk( ) )
  {
    os1 = m_oNameResults.GetFullPath( );
    m_osErrMsg.Empty( );
    if( os1.IsEmpty( ) ) m_osErrMsg << wxT("The results file has not been set.");
    else                 m_osErrMsg << wxT("The results file doesn't exist : ") << os1;
    return( false );
  }

  // Append input file name to argument list
  if( ! bSetArgLst( m_oNameResults.GetFullPath( ) ) ) return( false );

  // Filter the file before passing it to the waveform viewer process
  if( ! bFilterFile( ) )                              return( false );

  // Execute the process
  if( ! PrcBase::bExecAsync( ) )                      return( false );

  return( true );
}

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