// WManager.cc
//
// Implementation of working part
//
// 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 <cstdlib>                                // 'exit'
#include <cstring>                                // only for 'strchr'
#include <iostream>
#include <pwd.h>                                  // for home directory
#include <unistd.h>				  //
#include <sys/types.h>          		  // these two for getuid 


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


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

using namespace std;

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


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

  delete _Interface;
  delete _ConfigurationFilename;
}


// initialization stuff
void
WManager::Init()
{
#if DEBUG == 1
  cerr << "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";

  if (access (configuration_filename.c_str(), R_OK) != 0
      && access ("/etc/X11/wmanagerrc", R_OK) == 0)
    configuration_filename = "/etc/X11/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
  cerr << "WManager::CheckArguments(int, char**)\n";
#endif


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

  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
	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
	// Skip the -r prefix.
	*_ConfigurationFilename = argv[i]+2;
      } else {

	// copy argument to new array
	array[n] = strdup(argv[i]);
	n++;
      }
    } // end if
  } // end for
  
  argv = array;

  return argc-j;
}


// parse configuration file 
void
WManager::ParseFile()
{
#if DEBUG == 1
  cerr << "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
  cerr << "WManager::Run()\n";
#endif

  _Interface->Run(argc, argv);
}



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

// parse configuration file
void
WManager::_ParseConfigurationFile(ifstream* filestream)
{
#if DEBUG == 1
  cerr << "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
  cerr << "WManager::_TokenizeAndAddToBrowswer(char*)\n";
#endif

  string* name = 0;
  string* path = 0;


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

    name = new string();

    char * const eqsign = strchr(entry, '=');

    // test for failure
    if(eqsign != 0) {
      *eqsign = '\0';
      *name += entry;

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

      path = new string();
      *path += eqsign + 1;

#if DEBUG == 1
      cerr << "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->c_str());
    } // end if
  } // end if
}
