/* 
    kwintv, Video4Linux based TV application

    Copyright (C) 1998,1999 Moritz Wenk (wenk@mathematik.uni-kl.de)

    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.
*/

#ifdef HAVE_CONFIG_H
#include <config.h>  // config.h by configure
#endif

#ifdef myDEBUG
#define pDEBUG
#endif

#include <stdio.h>
#include <stdlib.h>
#include <sys/utsname.h>
#include "parsecl.h"

parsecl::parsecl(int _argc, char **_argv)
{
  argc=_argc;
  argv=_argv;

  list= new QStrList; // do deep copies
  oplist= new QList<option>;
}

parsecl::~parsecl()
{
  delete list;
  delete oplist;
}

bool parsecl::parse()
{
  int i;
  int pos;

  for (i=1; i < argc; i++ ) {
    QString qargv( argv[i] );
    if ( (pos=qargv.find('=')) != -1 ) {
      list->append( qargv.left(pos) );
      list->append( qargv.mid(pos+1,qargv.length()) );
    } else {
      list->append( argv[i] );
    }
  }

#ifdef pDEBUG
  unsigned int ui;
  if ( !list->isEmpty() ) {
    for ( ui= 0; ui < list->count(); ui++ ) {
      debug("parsecl: argv: %d: %s",ui,(const char*)list->at(ui));
    }
  }
  if ( !oplist->isEmpty() ) {
    for ( ui= 0; ui < oplist->count(); ui++ ) {
      debug("parsecl: %d: %s, %s, %s, %d",ui,
	    (const char*)oplist->at(ui)->oshort,
	    (const char*)oplist->at(ui)->olong,
	    (const char*)oplist->at(ui)->options,
	    oplist->at(ui)->oid);
    }
  }
  debug("parsecl:parsing for --help --version");
#endif

  if ( !list->isEmpty() ) {
    bool doexit=false;
    struct utsname uts;
    uname(&uts);
    if ( (list->find("-h") != -1) || (list->find("--help") != -1) ) {
      // show help
//      fprintf(stderr,"This is kWinTV %s, running on %s/%s (%s)\n\n",
//	      VERSION,uts.sysname,uts.machine,uts.release);

      if ( !oplist->isEmpty() ) {

	QString outstr;

	fprintf(stderr,"usage: kWinTV [options]\noptions:\n");
	option *op= oplist->first();
	while( op ) {
	  outstr.remove( 0, outstr.length() );
	  outstr+=op->oshort;
	  outstr.append("  ");
	  outstr+=op->olong;
	  if ( !op->options.isNull() ) {
	    outstr.append("=");
	    outstr+=op->options;
	  }
	  outstr=outstr.leftJustify(26,' ');
	  outstr+=op->help;
	  fprintf(stderr,"  %s\n",(const char *)outstr);

	  op= oplist->next();
	}
	outstr="-h  --help";
	outstr=outstr.leftJustify(26,' ');
	outstr+="print this text";
	fprintf(stderr,"  %s\n",(const char *)outstr);
	outstr="-v  --version";
	outstr=outstr.leftJustify(26,' ');
	outstr+="print the version";
	fprintf(stderr,"  %s\n",(const char *)outstr);
      }
      doexit=true;
    } 
    if ( (list->find("-v") != -1) || (list->find("--version") != -1) ) {
//      fprintf(stderr,"This is kWinTV %s, running on %s/%s (%s)\n\n",
//	      VERSION,uts.sysname,uts.machine,uts.release);
      doexit=true;
    }

    if ( doexit ) {
      exit(0);
    }

    return doexit;
  }
  return false;
}

bool parsecl::addOption( int oid, const char * oshort, const char * olong, 
			 const char * options, const char * help )
{
  option *op;
  if ( !oplist->isEmpty() ) {
    op= oplist->first();
    while( op ) {
      if ( oid == op->oid ) {
	warning("parsecl: id must be unique! %d, %s == %s",
		op->oid,(const char*)op->olong,olong);
	return false;
      }
      op= oplist->next();
    }
  }

  op= new option;
  op->oshort= oshort;
  op->olong= olong;
  op->options= options;
  op->help= help;
  op->oid= oid;
  oplist->append( op );
  
  return true;
}

bool parsecl::checkOptionBool( int oid, bool odefault )
{
#ifdef pDEBUG
  debug("parsecl: checkOptionBool %d, default %d",oid,odefault);
#endif
  if ( !oplist->isEmpty() ) {
    option *op= oplist->first();
    while( op ) {
      if ( ( op->oid == oid ) ) break;
      op= oplist->next();
    }
    if ( op && ((list->find(op->oshort) != -1) || (list->find(op->olong) != -1)) ) {
      if ( list->next() == "on" ) 
	return !odefault;
    }
  }
  return odefault;
}

int parsecl::checkOptionInt( int oid, int odefault )
{
#ifdef pDEBUG
  debug("parsecl: checkOptionInt  %d, default %d",oid,odefault);
#endif
  if ( !oplist->isEmpty() ) {
    option *op= oplist->first();
    while( op ) {
      if ( ( op->oid == oid ) ) break;
      op= oplist->next();
    }
    if ( op && ((list->find(op->oshort) != -1) || (list->find(op->olong) != -1)) ) {
      QString qsval( list->next() );
      bool ok;
      int retval= qsval.toInt( &ok );
      if ( !ok ) {
	warning("parsecl: bad option for %s,  %s: %s",
		(const char *)op->oshort,(const char *)op->olong,
		(const char *)qsval);
      } else {
#ifdef pDEBUG
  debug("parsecl: checkOptionInt  %d, returns %d",oid,retval);
#endif
	return retval;
      }
    }
  }
  return odefault;
}

const char * parsecl::checkOptionStr( int oid, const char * odefault )
{
#ifdef pDEBUG
  debug("parsecl: checkOptionBool %d, default %s",oid,odefault);
#endif
  if ( !oplist->isEmpty() ) {
    option *op= oplist->first();
    while( op ) {
      if ( ( op->oid == oid ) ) break;
      op= oplist->next();
    }
    if ( op && ((list->find(op->oshort) != -1) || (list->find(op->olong) != -1)) ) {
      return (const char *)list->next();
    }
  }
  return odefault;
}

bool parsecl::checkOptionSwitch( int oid, bool odefault  )
{
#ifdef pDEBUG
  debug("parsecl: checkOptionSwitch %d, default %d",oid,odefault);
#endif
  if ( !oplist->isEmpty() ) {
    option *op= oplist->first();
    while( op ) {
      if ( ( op->oid == oid ) ) break;
      op= oplist->next();
    }
    if ( op && ((list->find(op->oshort) != -1) || (list->find(op->olong) != -1)) ) {
      return !odefault;
    }
  }
  return odefault;
}










