//**************************************************************************************************
//                                          HelpTasks.cpp                                          *
//                                         ---------------                                         *
//  Started     : 2005-06-03                                                                       *
//  Last Update : 2018-10-16                                                                       *
//  Copyright   : (C) 2005-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 "HelpTasks.hpp"
#include "FrmMain.hpp"

// The application icons
#include "icons/gspiceui-32x32.xpm"
#include "icons/html-forward.xpm"
#include "icons/html-back.xpm"
#include "icons/html-close.xpm"

//**************************************************************************************************
// Implement an event table in which the events are routed to their respective handler functions in
// the class. If -1 is given as the ID, the given handler will be invoked for any event of the
// specified type.

wxBEGIN_EVENT_TABLE( HelpTasks, wxFrame )

  EVT_TOOL( HelpTasks::ID_TBR_FORWD, HelpTasks::OnToolForwd )
  EVT_TOOL( HelpTasks::ID_TBR_BCKWD, HelpTasks::OnToolBckwd )
  EVT_TOOL( HelpTasks::ID_TBR_CLOSE, HelpTasks::OnToolClose )

  EVT_CLOSE(                         HelpTasks::OnFrmClose  )

wxEND_EVENT_TABLE( )

//**************************************************************************************************
// Constructor.
//
// Argument List :
//   poFrmMain - A pointer to the parent frame

HelpTasks::HelpTasks( FrmMain * poFrmMain ) :
                      wxFrame( poFrmMain, -1, wxT(""), wxDefaultPosition, wxDefaultSize,
                               wxDEFAULT_FRAME_STYLE ),
                      m_oHtmlWin( this )
{
  // Set the pointer to the parent frame
  m_poFrmMain = poFrmMain;

  // Initialize the help viewer
  Initialize( );
}

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

HelpTasks::~HelpTasks( )
{
}

//**************************************************************************************************
// Initialize the main frame.

void  HelpTasks::Initialize( void )
{
  // Set the frame icon
  SetIcon( wxICON( gspiceui32x32 ) );

  // Set the frame title
  SetTitle( );

  // Call all the initialization functions
  InitInstPath( );
  InitToolBar ( );
  InitHtmlWin ( );
  InitPosnSize( );

  // Reduce the standard fonts sizes a bit
  m_oHtmlWin.SetStandardFonts( -1 );
}

//**************************************************************************************************
// Determine the path to the applications base installation path.

void  HelpTasks::InitInstPath( void )
{
  wxPathList  opl1;
  wxFileName  ofn1;
  wxString    os1;

  // Get the command used to envoke this process
  ofn1 = wxTheApp->argv[ 0 ];

  if( ! ofn1.GetPath( ).IsEmpty( ) )
  { // Extract the desired part of the path
    ofn1.Normalize( );  // Expand abbreviations eg. "..", "~', etc.
  }
  else
  { // Search env. var. PATH for the first occurrence of the app. name
    opl1.AddEnvList( wxT("PATH") );
    os1 = opl1.FindAbsoluteValidPath( ofn1.GetFullName( ) );
    ofn1 = os1;
  }

  m_rosInstallPath = ofn1.GetPath( );
  if( m_rosInstallPath.AfterLast( wxT('/') ) == wxT("bin") )
    m_rosInstallPath = m_rosInstallPath.BeforeLast( wxT('/') );
}

//**************************************************************************************************
// Initialize the tool bar.

void  HelpTasks::InitToolBar( void )
{
  wxBitmap  * poPixMap[ 3 ];
  wxToolBar * poToolBar;

  // Create the tool bar
  poToolBar = CreateToolBar( wxHORIZONTAL | wxTB_FLAT );

  // Create the bitmaps for the tools
  poPixMap[ 0 ] = new wxBitmap( html_back_xpm    );
  poPixMap[ 1 ] = new wxBitmap( html_forward_xpm );
  poPixMap[ 2 ] = new wxBitmap( html_close_xpm   );

  // Add the tools to the toolbar
  poToolBar->AddTool( ID_TBR_BCKWD, wxT(""), *(poPixMap[ 0 ]), wxT("Back")    );
  poToolBar->AddTool( ID_TBR_FORWD, wxT(""), *(poPixMap[ 1 ]), wxT("Forward") );
  poToolBar->AddTool( ID_TBR_CLOSE, wxT(""), *(poPixMap[ 2 ]), wxT("Close")   );

  // Realize the toolbar
  poToolBar->Realize( );

  // Can delete the bitmaps since they're reference counted
  for( int i1=0; i1<3; i1++ ) delete poPixMap[ i1 ];
}

//**************************************************************************************************
// Initialize the frames position amd size.

void  HelpTasks::InitHtmlWin( void )
{
  // Enable display of image types
  wxInitAllImageHandlers( );

  // Set suitable wxHtmlWindow font sizes
  int  ia[ 7 ]={ 9,10,11,14,16,18,20 };
  m_oHtmlWin.SetFonts( wxT(""), wxT(""), ia );
}

//**************************************************************************************************
// Initialize the frames position amd size.

void  HelpTasks::InitPosnSize( void )
{
  int  iPosnX, iPosnY, iSizeW, iSizeH;

  // Get the position and size from the configuration object
  iPosnX = g_oConfig.iGetHelpPosnX( );
  iPosnY = g_oConfig.iGetHelpPosnY( );
  iSizeW = g_oConfig.iGetHelpSizeW( );
  iSizeH = g_oConfig.iGetHelpSizeH( );

  // Set the position and size
  if( iPosnX>0 && iPosnY>0 ) Move( iPosnX, iPosnY );
  if( iSizeW>0 && iSizeH>0 ) SetClientSize( iSizeW, iSizeH );
}

//**************************************************************************************************
// Set the help frame title.

void  HelpTasks::SetTitle( void )
{
  wxString  os1;

  os1 = wxT("GNU Spice GUI - User Manual");

  if( ! m_oHtmlWin.GetOpenedPage( ).IsEmpty( ) )
    os1 << wxT("  -  ") << m_oHtmlWin.GetOpenedPage( );

  wxFrame::SetTitle( os1 );
}

//**************************************************************************************************
// Display the gSpiceUI User Manual.

void  HelpTasks::ManualUser( void )
{
  wxFileName  ofn1, ofn2;
  wxString    os1;

  // Check if the manual has been loaded into memory
  if( m_oHtmlWin.GetOpenedPage( ).IsEmpty( ) )
  {
    // Specify the two locations to search
    if( m_rosInstallPath.IsEmpty( ) ) return;
    ofn1 = m_rosInstallPath + wxT("/share/gspiceui/html/User-Manual.html");
    ofn2 = m_rosInstallPath + wxT("/html/User-Manual.html");

    // Search for the manual
    if(      ofn1.FileExists( ) ) os1 = ofn1.GetFullPath( );
    else if( ofn2.FileExists( ) ) os1 = ofn2.GetFullPath( );
    else
    {
      // Display an error message
      os1.Empty( );
      os1 << wxT("\nThe base manual page \"") << ofn1.GetFullName( ) << wxT('\"')
          << wxT(" couldn't be found in either of the following locations :\n\n")
          << wxT("     ") << ofn1.GetPath( ) << wxT("/\n")
          << wxT("     ") << ofn2.GetPath( ) << wxT("/\n");
      wxMessageBox( os1, wxT("User Manual"), wxOK | wxCENTRE, m_poFrmMain );
      return;
    }

    // Load the manual
    m_oHtmlWin.LoadPage( os1 );
    SetTitle( );
  }

  // Show the manual
  Show( true );
}

//**************************************************************************************************
// Display the about message dialog.

void  HelpTasks::About( void )
{
  wxString  os1;
  long      lStyle;

  os1 << wxT("\n                                     " ) << APP_NAME
      << wxT("\n                     Version ")          << APP_VERSION
                                            << wxT(" (") << APP_DATE << wxT(")")
      << wxT("\n               ")                        << APP_COPYRIGHT
      << wxT("\n\n")

      << wxT("\nThis application is intended to provide a GUI for various")
      << wxT("\nfreely available electronic circuit simulation engines :\n")
      << wxT("\n                 - NG-Spice")
      << wxT("\n                 - GNU-Cap\n")

      << wxT("\nSchematic files are imported using gnetlist and waveform     ")
      << wxT("\ndata can be viewed using either ") << rosEnumEngToStr( eSIMR_NGSPICE )
      << wxT(" or ") << rosEnumEngToStr( eSIMR_GNUCAP ) << wxT(".\n")

      << wxT("\nThis application is written in C++ and uses the wxWidgets")
      << wxT("\nlibrary which is a free and open source widget toolkit and")
      << wxT("\ntools library. wxWidgets version ")
      << wxMAJOR_VERSION << wxT('.') << wxMINOR_VERSION << wxT('.') << wxRELEASE_NUMBER
      << wxT(" was used in this")
      << wxT("\nbuild of ") << APP_NAME << wxT(".\n")

      << wxT("\n") << APP_NAME << wxT(" is free software; you can redistribute it and/or")
      << wxT("\nmodify it under the terms of the GNU Library General")
      << wxT("\nPublic Licence as published by the Free Software")
      << wxT("\nFoundation; either version 3 of the Licence, or (at your")
      << wxT("\noption) any later version.\n")

      << wxT("\n") << APP_NAME << wxT(" is distributed in the hope that it will be useful,")
      << wxT("\nbut WITHOUT ANY WARRANTY; without even the implied")
      << wxT("\nwarranty of MERCHANTABILITY or FITNESS FOR A")
      << wxT("\nPARTICULAR PURPOSE.");

  lStyle = wxOK | wxICON_INFORMATION;

  wxMessageBox( os1, wxT("About gSpiceUI"), lStyle, m_poFrmMain );
}

//**************************************************************************************************
// Go to the next page in the history store.
//
// Argument List :
//   roEvtCmd - The event to be processed

void  HelpTasks::OnToolForwd( wxCommandEvent & roEvtCmd )
{
  if( m_oHtmlWin.HistoryCanForward( ) )
    m_oHtmlWin.HistoryForward( );
}

//**************************************************************************************************
// Go to the previous page in the history store.
//
// Argument List :
//   roEvtCmd - The event to be processed

void  HelpTasks::OnToolBckwd( wxCommandEvent & roEvtCmd )
{
  if( m_oHtmlWin.HistoryCanBack( ) )
    m_oHtmlWin.HistoryBack( );
}

//**************************************************************************************************
// Close the help viewer frame.
//
// Argument List :
//   roEvtCmd - The event to be processed

void  HelpTasks::OnToolClose( wxCommandEvent & roEvtCmd )
{
  int  iPosnX, iPosnY, iSizeW, iSizeH;

  // Save the frame size and position
  GetPosition( &iPosnX, &iPosnY );
  GetClientSize( &iSizeW, &iSizeH );
  g_oConfig.bSetHelpPosnX( iPosnX );
  g_oConfig.bSetHelpPosnY( iPosnY );
  g_oConfig.bSetHelpSizeW( iSizeW );
  g_oConfig.bSetHelpSizeH( iSizeH );

  g_oConfig.bFlush( );  // Write changes to the configuration file

  Show( false );        // Hide the frame

  // Reset the HTML Window settings
  while( m_oHtmlWin.HistoryCanBack( ) )
    m_oHtmlWin.HistoryBack( );
  m_oHtmlWin.HistoryClear( );
  m_oHtmlWin.Scroll( 0, 0 );
}

//**************************************************************************************************
// Close the help viewer frame.
//
// Argument List :
//   roEvtClose - The event to be processed

void  HelpTasks::OnFrmClose( wxCloseEvent & roEvtClose )
{
  wxCommandEvent  oEvtCmd;

  OnToolClose( oEvtCmd );
}

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