// Author: Wim Lavrijsen, February 2006

// Bindings
#include "PyROOT.h"
#include "TPyROOTApplication.h"
#include "Utility.h"

// ROOT
#include "TROOT.h"
#include "TInterpreter.h"
#include "TSystem.h"
#include "TBenchmark.h"
#include "TStyle.h"
#include "TError.h"
#include "Getline.h"
//#include "TVirtualX.h"

// Standard
#include <string.h>


//______________________________________________________________________________
//                   Setup interactive application for python
//                   ========================================
//
// The TPyROOTApplication sets up the nuts and bolts for interactive ROOT use
// from python, closely following TRint. Note that not everything is done here,
// some bits (such as e.g. the use of exception hook for shell escapes) are more
// easily done in python and you'll thus find them ROOT.py
//
// The intended use of this class is from python only. It is used by default in
// ROOT.py, so if you do not want to have a TApplication derived object created
// for you, you'll need to load libPyROOT.so instead.
//
// The static InitXYZ functions are used in conjunction with TPyROOTApplication
// in ROOT.py, but they can be used independently.
//
// NOTE: This class will receive the command line arguments from sys.argv. A
// distinction between arguments for TApplication and user arguments can be
// made by using "-" or "--" as a separator on the command line.


//- data ---------------------------------------------------------------------
ClassImp(PyROOT::TPyROOTApplication)


//- constructors/destructor --------------------------------------------------
PyROOT::TPyROOTApplication::TPyROOTApplication(
   const char* acn, int* argc, char** argv, Bool_t bLoadLibs ) :
      TApplication( acn, argc, argv )
{
// Create a TApplication derived for use with interactive ROOT from python. A
// set of standard, often used libs is loaded if bLoadLibs is true (default).

   if ( bLoadLibs )   // note that this section could be programmed in python
   {
   // follow TRint to minimize differences with root.exe (note: changed <pair>
   // to <utility> for Cling, which is correct)
      ProcessLine( "#include <iostream>", kTRUE );
      ProcessLine( "#include <string>",   kTRUE ); // for std::string iostream.
      ProcessLine( "#include <vector>",   kTRUE ); // needed because they're used within the
      ProcessLine( "#include <utility>",  kTRUE ); //  core ROOT dicts and CINT won't be able
                                                   //  to properly unload these files
   }

#ifdef WIN32
   // switch win32 proxy main thread id
   if (gVirtualX)
      ProcessLine("((TGWin32 *)gVirtualX)->SetUserThreadId(0);", kTRUE);
#endif

// save current interpreter context
   gInterpreter->SaveContext();
   gInterpreter->SaveGlobalsContext();

// prevent crashes on accessing history
   Gl_histinit( (char*)"-" );

// prevent ROOT from exiting python
   SetReturnFromRun( kTRUE );
}


//- static public members ----------------------------------------------------
Bool_t PyROOT::TPyROOTApplication::CreatePyROOTApplication( Bool_t bLoadLibs )
{
// Create a TPyROOTApplication. Returns false if gApplication is not null.

   if ( ! gApplication ) {
   // retrieve arg list from python, translate to raw C, pass on
      PyObject* argl = PySys_GetObject( const_cast< char* >( "argv" ) );

      int argc = 1;
      if ( argl && 0 < PyList_Size( argl ) ) argc = (int)PyList_GET_SIZE( argl );
      char** argv = new char*[ argc ];
      for ( int i = 1; i < argc; ++i ) {
         char* argi = PyROOT_PyUnicode_AsString( PyList_GET_ITEM( argl, i ) );
         if ( strcmp( argi, "-" ) == 0 || strcmp( argi, "--" ) == 0 ) {
         // stop collecting options, the remaining are for the python script
            argc = i;    // includes program name
            break;
         }
         argv[ i ] = argi;
      }
#if PY_VERSION_HEX < 0x03000000
      if ( Py_GetProgramName() && strlen( Py_GetProgramName() ) != 0 )
         argv[ 0 ] = Py_GetProgramName();
      else
         argv[ 0 ] = (char*)"python";
#else
// TODO: convert the wchar_t*
      argv[ 0 ] = (char*)"python";
#endif

      gApplication = new TPyROOTApplication( "PyROOT", &argc, argv, bLoadLibs );
      delete[] argv;     // TApplication ctor has copied argv, so done with it

      return kTRUE;
   }

   return kFALSE;
}

//____________________________________________________________________________
Bool_t PyROOT::TPyROOTApplication::InitROOTGlobals()
{
// Setup the basic ROOT globals gBenchmark, gStyle, gProgname, if not already
// set. Always returns true.

   if ( ! gBenchmark ) gBenchmark = new TBenchmark();
   if ( ! gStyle ) gStyle = new TStyle();

   if ( ! gProgName )              // should have been set by TApplication
#if PY_VERSION_HEX < 0x03000000
      gSystem->SetProgname( Py_GetProgramName() );
#else
// TODO: convert the wchar_t*
      gSystem->SetProgname( "python" );
#endif

   return kTRUE;
}

//____________________________________________________________________________
Bool_t PyROOT::TPyROOTApplication::InitROOTMessageCallback()
{
// Install ROOT message handler which will turn ROOT error message into
// python exceptions. Always returns true.

   SetErrorHandler( (ErrorHandlerFunc_t)&Utility::ErrMsgHandler );
   return kTRUE;
}
 TPyROOTApplication.cxx:1
 TPyROOTApplication.cxx:2
 TPyROOTApplication.cxx:3
 TPyROOTApplication.cxx:4
 TPyROOTApplication.cxx:5
 TPyROOTApplication.cxx:6
 TPyROOTApplication.cxx:7
 TPyROOTApplication.cxx:8
 TPyROOTApplication.cxx:9
 TPyROOTApplication.cxx:10
 TPyROOTApplication.cxx:11
 TPyROOTApplication.cxx:12
 TPyROOTApplication.cxx:13
 TPyROOTApplication.cxx:14
 TPyROOTApplication.cxx:15
 TPyROOTApplication.cxx:16
 TPyROOTApplication.cxx:17
 TPyROOTApplication.cxx:18
 TPyROOTApplication.cxx:19
 TPyROOTApplication.cxx:20
 TPyROOTApplication.cxx:21
 TPyROOTApplication.cxx:22
 TPyROOTApplication.cxx:23
 TPyROOTApplication.cxx:24
 TPyROOTApplication.cxx:25
 TPyROOTApplication.cxx:26
 TPyROOTApplication.cxx:27
 TPyROOTApplication.cxx:28
 TPyROOTApplication.cxx:29
 TPyROOTApplication.cxx:30
 TPyROOTApplication.cxx:31
 TPyROOTApplication.cxx:32
 TPyROOTApplication.cxx:33
 TPyROOTApplication.cxx:34
 TPyROOTApplication.cxx:35
 TPyROOTApplication.cxx:36
 TPyROOTApplication.cxx:37
 TPyROOTApplication.cxx:38
 TPyROOTApplication.cxx:39
 TPyROOTApplication.cxx:40
 TPyROOTApplication.cxx:41
 TPyROOTApplication.cxx:42
 TPyROOTApplication.cxx:43
 TPyROOTApplication.cxx:44
 TPyROOTApplication.cxx:45
 TPyROOTApplication.cxx:46
 TPyROOTApplication.cxx:47
 TPyROOTApplication.cxx:48
 TPyROOTApplication.cxx:49
 TPyROOTApplication.cxx:50
 TPyROOTApplication.cxx:51
 TPyROOTApplication.cxx:52
 TPyROOTApplication.cxx:53
 TPyROOTApplication.cxx:54
 TPyROOTApplication.cxx:55
 TPyROOTApplication.cxx:56
 TPyROOTApplication.cxx:57
 TPyROOTApplication.cxx:58
 TPyROOTApplication.cxx:59
 TPyROOTApplication.cxx:60
 TPyROOTApplication.cxx:61
 TPyROOTApplication.cxx:62
 TPyROOTApplication.cxx:63
 TPyROOTApplication.cxx:64
 TPyROOTApplication.cxx:65
 TPyROOTApplication.cxx:66
 TPyROOTApplication.cxx:67
 TPyROOTApplication.cxx:68
 TPyROOTApplication.cxx:69
 TPyROOTApplication.cxx:70
 TPyROOTApplication.cxx:71
 TPyROOTApplication.cxx:72
 TPyROOTApplication.cxx:73
 TPyROOTApplication.cxx:74
 TPyROOTApplication.cxx:75
 TPyROOTApplication.cxx:76
 TPyROOTApplication.cxx:77
 TPyROOTApplication.cxx:78
 TPyROOTApplication.cxx:79
 TPyROOTApplication.cxx:80
 TPyROOTApplication.cxx:81
 TPyROOTApplication.cxx:82
 TPyROOTApplication.cxx:83
 TPyROOTApplication.cxx:84
 TPyROOTApplication.cxx:85
 TPyROOTApplication.cxx:86
 TPyROOTApplication.cxx:87
 TPyROOTApplication.cxx:88
 TPyROOTApplication.cxx:89
 TPyROOTApplication.cxx:90
 TPyROOTApplication.cxx:91
 TPyROOTApplication.cxx:92
 TPyROOTApplication.cxx:93
 TPyROOTApplication.cxx:94
 TPyROOTApplication.cxx:95
 TPyROOTApplication.cxx:96
 TPyROOTApplication.cxx:97
 TPyROOTApplication.cxx:98
 TPyROOTApplication.cxx:99
 TPyROOTApplication.cxx:100
 TPyROOTApplication.cxx:101
 TPyROOTApplication.cxx:102
 TPyROOTApplication.cxx:103
 TPyROOTApplication.cxx:104
 TPyROOTApplication.cxx:105
 TPyROOTApplication.cxx:106
 TPyROOTApplication.cxx:107
 TPyROOTApplication.cxx:108
 TPyROOTApplication.cxx:109
 TPyROOTApplication.cxx:110
 TPyROOTApplication.cxx:111
 TPyROOTApplication.cxx:112
 TPyROOTApplication.cxx:113
 TPyROOTApplication.cxx:114
 TPyROOTApplication.cxx:115
 TPyROOTApplication.cxx:116
 TPyROOTApplication.cxx:117
 TPyROOTApplication.cxx:118
 TPyROOTApplication.cxx:119
 TPyROOTApplication.cxx:120
 TPyROOTApplication.cxx:121
 TPyROOTApplication.cxx:122
 TPyROOTApplication.cxx:123
 TPyROOTApplication.cxx:124
 TPyROOTApplication.cxx:125
 TPyROOTApplication.cxx:126
 TPyROOTApplication.cxx:127
 TPyROOTApplication.cxx:128
 TPyROOTApplication.cxx:129
 TPyROOTApplication.cxx:130
 TPyROOTApplication.cxx:131
 TPyROOTApplication.cxx:132
 TPyROOTApplication.cxx:133
 TPyROOTApplication.cxx:134
 TPyROOTApplication.cxx:135
 TPyROOTApplication.cxx:136
 TPyROOTApplication.cxx:137
 TPyROOTApplication.cxx:138
 TPyROOTApplication.cxx:139
 TPyROOTApplication.cxx:140
 TPyROOTApplication.cxx:141
 TPyROOTApplication.cxx:142
 TPyROOTApplication.cxx:143
 TPyROOTApplication.cxx:144
 TPyROOTApplication.cxx:145
 TPyROOTApplication.cxx:146
 TPyROOTApplication.cxx:147
 TPyROOTApplication.cxx:148
 TPyROOTApplication.cxx:149
 TPyROOTApplication.cxx:150
 TPyROOTApplication.cxx:151
 TPyROOTApplication.cxx:152