// WManager.cc
//
// Implementation of working part
// $Id: WManager.cc,v 1.3 1999/11/14 15:28:36 M Exp $
//
//
// Copyright (C) 1999  M. Tessmer
//
// 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 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


// SYSTEM INCLUDES /////////////////////////////////
#include <string>                                 // standard string class
#include <fstream>                                // file streams
#include <cstring>                                // only for 'strtok'
#include <pwd.h>                                  // for home directory


// PROJECT INCLUDES ////////////////////////////////
#include "Interface.H"                            // interface class
#include "WManager.H"                             // class definition


// LOCAL INCLUDES //////////////////////////////////
#include <FL/fl_message.H>                        // message window


// constructor
WManager::WManager()
  : _Interface(0), _ConfigurationFilename(0)
{
#if DEBUG == 1
  cout << "WManager::WManager()\n";
#endif
}


// destructor
WManager::~WManager()
{
#if DEBUG == 1
  cout << "WManager::~WManager()\n";
#endif

  delete _Interface;
  delete _ConfigurationFilename;
}


// initialization stuff
void
WManager::Init()
{
#if DEBUG == 1
  cout << "WManager::Init()\n";
#endif

  string configuration_filename  = "";
  struct passwd* my_passwd;

  // find home directory and add '.wmanagerrc'
  my_passwd = getpwuid(getuid());
  configuration_filename += my_passwd->pw_dir;
  configuration_filename += "/.wmanagerrc";

  _ConfigurationFilename = new string(configuration_filename.c_str());

  _Interface = new Interface();
  _Interface->Init();
}


// check commandline for alternative configuration file ('-r filename')
int
WManager::CheckArguments(int    argc,
			 char** argv)
{
#if DEBUG == 1
  cout << "WManager::CheckArguments(int, char**)\n";
#endif


  int    i     = 0;                               // old array index
  int    n     = 0;                               // new array index
  int    j     = 0;                               // 1 || 2

  char*  str   = 0;
  char** array = 0;
  bool   flag  = false;

  
  //
  // pass one: check for no. of arguments and for unity
  //
  for(i = 0; i<argc; i++) {

    if( strcmp(argv[i], "-r") == 0 ) {
      
      if(flag) {
	cerr << "Error. Used option -r twice!\n";
	exit(-1);
      } else {
	
	// we must delete two arguments
	cout << "Found -r alone. Must delete two arguments\n";
	j = 2;
	flag = true;
      }
    } else {

      if(argv[i][0] == '-' && argv[i][1] == 'r') {

	if(flag) {
	  cerr << "Error. Used -r twice!\n";
	  exit(-1);
	} else {

	  // we must delete only one argument
	  j = 1;
	  flag = true;
	}
      }
      
    } // end if
  } // end for


  //
  // pass two: build up new argv array
  //
  array = new char*[argc-j];
  n = 0;

  for(i = 0; i<argc; i++) {
    
    if( strcmp(argv[i], "-r") == 0 ) {

      // we must delete two arguments
      i++;
    
      *_ConfigurationFilename = "";
      *_ConfigurationFilename += argv[i];
    } else {

      if(argv[i][0] == '-' && argv[i][1] == 'r') {
	
	// we must delete only one argument
	*_ConfigurationFilename = "";
	*_ConfigurationFilename += _CutString(argv[i], "-r");
      } else {

	// copy argument to new array
	str = new char[strlen(argv[i])+1];
	strcpy(str, argv[i]);
	array[n] = str;

	n++;
      }
    } // end if
  } // end for
  
  argv = array;

  return argc-j;
}


// parse configuration file 
void
WManager::ParseFile()
{
#if DEBUG == 1
  cout << "WManager::ParseFile()\n";
#endif

  // file descriptor
  ifstream* fd = 0;

  
  fd = new ifstream();
  if(fd == 0) {
    fl_alert("Cannot open configuration file!\n Exiting for now.");
  } else {
  
    // try to open file
    fd->open(_ConfigurationFilename->c_str());
    if(!fd->is_open()) {
      fl_alert("Cannot open file %s", _ConfigurationFilename->c_str());
      cout << "-1\n";
      exit(-1);
    }

  } // end if
  
  _ParseConfigurationFile(fd);
  

  delete fd;
}


// enter fltk run loop
void
WManager::Run(int argc, char** argv)
{
#if DEBUG == 1
  cout << "WManager::Run()\n";
#endif

  _Interface->Run(argc, argv);
}



// PRIVATE SECTION ////////////////////////////////////////////////////////////

// parse configuration file
void
WManager::_ParseConfigurationFile(ifstream* filestream)
{
#if DEBUG == 1
  cout << "WManager::_ParseConfigurationFile(ifstream*)\n";
#endif
  
  // because of a lack in iostream you cannot read lines into strings with
  // iostream::getline; the use of a char buffer is a workaround

  char*   dummy = 0;


  dummy = new char[200+1];                        // workaround

  while(!filestream->eof()) {

    filestream->getline(dummy, 200);                // workaround
    if(strcmp(dummy, "") != 0) {
      _TokenizeAndAddToBrowser(dummy);
    }

  } // end while
}


// add token to fltk browser widget
void
WManager::_TokenizeAndAddToBrowser(char* entry)
{
#if DEBUG == 1
  cout << "WManager::_TokenizeAndAddToBrowswer(char*)\n";
#endif

  string* name = 0;
  string* path = 0;
  char*   ptr  = 0;


  if(entry[0] != '#') {

    name = new string();

    *name += strtok(entry, "=");

#if DEBUG == 1
    cout << "WManager::_TokenizeAndAddToBrowser: name = <"
	 << *name
	 << ">\n";
#endif

    // path to executable
    ptr = strtok(0, "=");

    // test for failure
    if(ptr != 0) {
      
      path = new string();
      *path += ptr;

#if DEBUG == 1
      cout << "WManager::_TokenizeAndAddToBrowser: path = <"
	   << *path
	   << ">\n";
#endif

      // add new entry to browser list
      _Interface->AddToBrowser(name->c_str(), path->c_str());
      
      // clean up
      delete name;
      delete path;
    } else {
      fl_alert("Error near %s while parsing configuration file %s!"
	       "Try to read on...",
	       name->c_str(), _ConfigurationFilename);
    } // end if
  } // end if
}


// cut rest from the beginning of str
char*
WManager::_CutString(char* str, char* rest)
{
  int   i          = 0;
  int   n          = 0;
  int   length     = 0;
  int   new_length = 0;
  char* new_str    = 0;
  

  length = strlen(str);
  new_length = length - strlen(rest);

  if(new_length < 0)
    return 0;
  
  new_str = new char[new_length+1];

  for(i = strlen(rest), n = 0;
      i < length;
      i++, n++) {
    new_str[n] = str[i];
  }
  new_str[new_length+1] = 0;

  return new_str;
}
