// C++ code Copyright (C) David R. Evans G4AMJ/NQ0I

// class for batch mode of MIDAS

#ifndef SMBATCHMODEH
#define SMBATCHMODEH

#include <DREstring.h>
#include <list.h>
#include <sm_mode.h>

#include <fstream.h>
#include <iostream.h>

// strict compilers do not permit casts from pointers to member functions
// to void pointers. Consequently, we cannot place an address of a
// member function on to a generic list. This is a pain, and requires
// the following workaround quick and dirty class

class batch_mode;

#ifdef __BORLANDC__
class windows_batch_mode;

typedef int (windows_batch_mode::*PMFSS)(DREstring&, DREstring&);

class memberfunctionlist
{ PMFSS array[50];
  int index;

public:
  memberfunctionlist(void) : index(0) { }

  inline void operator+=(PMFSS pmfss)
    { array[++index] = pmfss; }          // the zeroth element is unused
  inline int length(void)
    { return index; }
  inline PMFSS operator[](const int n)
    { return array[n]; } 
};
#endif

#ifdef SUN
typedef int (batch_mode::*PMFSS)(DREstring&, DREstring&);

typedef glist memberfunctionlist;
#endif

class batch_mode : public operating_mode
{ 
protected:
  boolean echo, _verbose;
  ifstream* file;
  glist known_commands;
  memberfunctionlist dispatch_functions;
  PMFSS _current_dispatch_function;

  DREstring command_line, _current_command, _current_parameters;
  
// private functions

  void _invalid_parameter(DREstring&, DREstring&);

  int _batch_file_comment(DREstring&, DREstring&);
  int _comment(DREstring&, DREstring&);
  int _echo(DREstring&, DREstring&);
  int _exit(DREstring&, DREstring&);
  int _first(DREstring&, DREstring&);
  int _infiletype(DREstring&, DREstring&);
  int _next(DREstring&, DREstring&);
  int _Open(DREstring&, DREstring&);
  int _plot(DREstring&, DREstring&);
  int _plotall(DREstring&, DREstring&);
  int _plotmode(DREstring&, DREstring&);
  virtual int _print(DREstring&, DREstring&);

// We _must_ define a _set function so as to determine what parameters
// are settable in a derived object
  virtual int _set(DREstring&, DREstring&) = 0;
  int _show(DREstring&, DREstring&);
  int _verbose_toggle(DREstring&, DREstring&);
  int _version(DREstring&, DREstring&);
 
  void _set_scmode(DREstring&);
  void _set_pramode(DREstring&);
  void _set_plotmode(DREstring&);

  virtual void _show_pra_modes(void);
  virtual void _show_sc_modes(void);
//  void _show_pra_mode(void);
  virtual void _show_sc_mode(void);
  virtual void _show_range(void);
  inline virtual void verbose(DREstring& msg)
    { if (_verbose) then 
      display_status(msg);
    }

  virtual void _generate_command_list(void) = 0;
  virtual void _initialise(void);

  void _parse_command_line(void);
  
public:
  batch_mode(void);		// used for vga constructor
  batch_mode(const char* filename, const float rev_nr);
  virtual ~batch_mode(void);

// read and execute the file
  virtual void execute(void) = 0;

// is a command valid? Returns command number (wrt 1)
  int valid_string(DREstring&, glist&);
  int valid_string(DREstring&, list<DREstring>&);
  
  virtual void clear_status(void)
    { cout << "\r                    \r"; }
  virtual void echo_command(DREstring& cmd)
    { cout << cmd << endl; }
  virtual void display_status(DREstring&);
  virtual void error(DREstring& msg)
    { fatal_error(msg); }
};

extern batch_mode* bmode;

#endif
