// ============================================================================
/*!
//
//  \file TArgument.hh
//  \brief This file contains the TArgument class.
//  \author Go IWAI <goiwai@users.sourceforge.jp>
//
//  $Id: TArgument.hh,v 1.6 2004/03/07 10:30:34 goiwai Exp $
//  $Name: CLDAQ-1-14-06 $
//  $Log: TArgument.hh,v $
//  Revision 1.6  2004/03/07 10:30:34  goiwai
//  ROOTに組みこむためのおまじないマクロを埋めこみました。
//  全てにおいて完全に動作するわけではありません。
//
//  Revision 1.5  2004/03/01 03:56:15  goiwai
//  コメントいれただけ
//
//  Revision 1.4  2004/01/19 21:09:43  goiwai
//  プリプロセッサの接頭辞をCLDAQ__に変更しました.
//
//  Revision 1.3  2003/11/03 08:35:15  goiwai
//  Doxygen用のタグとコメントをうちこんでいく試みを開始しました.
//
//  Revision 1.2  2003/10/10 09:37:56  goiwai
//  データメンバに theUsage を追加しました.
//
//  Revision 1.1  2003/10/06 16:32:25  goiwai
//  GNUスタイルの引数を簡単にかつ直感的に解釈するための部品です.
//
*/
// ============================================================================
#ifndef CLDAQ__TARGUMENT_HH
#define CLDAQ__TARGUMENT_HH

#include "Tglobals.h"
#include "TOptionTable.hh"
#include "TOptionMap.hh"


/*!
// \example
//
// If example code exists.
//
*/

/*!
// \class TArgument
// \brief This is the TArgument class.
// \author Go IWAI <goiwai@users.sourceforge.jp>
//
// The TArgument class detail description.
// Write it down ASAP!
//
// \todo Perlモジュールみたいにしたい regex が必要
// \todo 関数とのバインド
//  my $retval = 
//    GetOptions("o|d|dir|output-dir|output=s"        => \$output,
//               "i|image|image-format|format=s"      => \$format,
//               "f|force"                            => \$force,
//               "p|ps|postscript|with-postscript"    => \$ps,
//               "h|help"                             => \$help,
//               "v|version"                          => \$version);
// \bug None?
// \ingroup SystemCategory
*/
class TArgument
{

  private:
    Tint theNumberOfOriginalArguments;
    Tchar** theOriginalArguments;
    TOptionTable theOptionTable;
    TOptionMap theOptionMap;
    Tstring theProgramName;
    Tstring theDirectoryName;
    TstringList theElements;
    Tint theNumberOfElements;
    Tstring theUsage;

  public:
    TArgument( Tint argc, Tchar** argv, const Tstring& usage = "" );
    TArgument( Tint argc, Tchar** argv, const TOptionTable& table, const Tstring& usage = "" );
    ~TArgument();

  public:
    Tvoid Analyse();
    Tvoid ShowUsage() const;
    Tvoid ShowVersion() const;
    Tvoid ShowHelp() const;

  public:
    Tstring operator[]( Tint index ) const;
    Tstring operator[]( const TOption& option ) const;
    Tstring operator[]( const Tstring& optionname ) const;

  public:
    friend Tostream& operator<<( Tostream& tos, const TArgument& right );

  public:
    Tint GetNumberOfOriginalArguments() const;
    Tchar** GetOriginalArguments() const;
    const TOptionTable& GetOptionTable() const;
    const TOptionMap& GetOptionMap() const;
    const Tstring& GetProgramName() const;
    const Tstring& GetDirectoryName() const;
    const TstringList& GetElements() const;
    Tint GetNumberOfElements() const;
    const Tstring& GetUsage() const;
    Tvoid SetUsage( const Tstring& usage );

  public:
    Tbool HasOption( const TOption& option ) const;
    Tbool HasOption( const Tstring& optionname ) const;
    Tstring GetParameter( Tint index ) const;
    Tstring GetParameter( const Tstring& optionname ) const;
    Tstring GetParameter( const TOption& option ) const;
    Tint GetIntegerParameter( Tint index ) const;
    Tint GetIntegerParameter( const Tstring& optionname ) const;
    Tint GetIntegerParameter( const TOption& option ) const;
    Tdouble GetDoubleParameter( Tint index ) const;
    Tdouble GetDoubleParameter( const Tstring& optionname ) const;
    Tdouble GetDoubleParameter( const TOption& option ) const;
    TintList GetIntegerElements() const;
    TdoubleList GetDoubleElements() const;
    Tstring GetElement( Tint index ) const;
    Tint GetIntegerElement( Tint index ) const;
    Tdouble GetDoubleElement( Tint index ) const;

#ifdef __CLDAQ_ROOT_DLL
    ClassDef(TArgument,0)
#endif

};

inline Tint TArgument::GetNumberOfOriginalArguments() const
{
  return theNumberOfOriginalArguments;
}

inline Tchar** TArgument::GetOriginalArguments() const
{
  return theOriginalArguments;
}

inline const TOptionTable& TArgument::GetOptionTable() const
{
  return theOptionTable;
}

inline const TOptionMap& TArgument::GetOptionMap() const
{
  return theOptionMap;
}

inline const Tstring& TArgument::GetProgramName() const
{
  return theProgramName;
}

inline const Tstring& TArgument::GetDirectoryName() const
{
  return theDirectoryName;
}

inline const TstringList& TArgument::GetElements() const
{
  return theElements;
}

inline Tint TArgument::GetNumberOfElements() const
{
  return theNumberOfElements;
}

inline Tbool TArgument::HasOption( const TOption& option ) const
{
  return theOptionMap.HasOption( option );
}

inline Tbool TArgument::HasOption( const Tstring& optionname ) const
{
  return theOptionMap.HasOption( optionname );
}

inline Tstring TArgument::GetParameter( Tint index ) const
{
  return theOptionMap.GetParameter( index );
}

inline Tstring TArgument::GetParameter( const Tstring& optionname ) const
{
  return theOptionMap.GetParameter( optionname );
}

inline Tstring TArgument::GetParameter( const TOption& option ) const
{
  return theOptionMap.GetParameter( option );
}

inline Tint TArgument::GetIntegerParameter( Tint index ) const
{
  return strtoi( GetParameter( index ) );
}

inline Tint TArgument::GetIntegerParameter( const Tstring& optionname ) const
{
  return strtoi( GetParameter( optionname ) );
}

inline Tint TArgument::GetIntegerParameter( const TOption& option ) const
{
  return strtoi( GetParameter( option ) );
}

inline Tdouble TArgument::GetDoubleParameter( Tint index ) const
{
  return strtod( GetParameter( index ) );
}

inline Tdouble TArgument::GetDoubleParameter( const Tstring& optionname ) const
{
  return strtod( GetParameter( optionname ) );
}

inline Tdouble TArgument::GetDoubleParameter( const TOption& option ) const
{
  return strtod( GetParameter( option ) );
}

inline TintList TArgument::GetIntegerElements() const
{
  TintList retval;
  for ( Tint i = 0; i < theNumberOfElements; i ++ ) {
    retval.push_back( strtoi( theElements[ i ] ) );
  }
  return retval;
}

inline TdoubleList TArgument::GetDoubleElements() const
{
  TdoubleList retval;
  for ( Tint i = 0; i < theNumberOfElements; i ++ ) {
    retval.push_back( strtod( theElements[ i ] ) );
  }
  return retval;
}

inline Tstring TArgument::GetElement( Tint index ) const
{
  Tstring retval = "";
  Tint listlen = (Tint)theElements.size();
  if ( index >= 0 && index < listlen && !theElements.empty() ) {
    retval = theElements[ index ];
  }
  return retval;
}

inline Tint TArgument::GetIntegerElement( Tint index ) const
{
  return strtoi( GetElement( index ) );
}

inline Tdouble TArgument::GetDoubleElement( Tint index ) const
{
  return strtod( GetElement( index ) );
}

inline Tstring TArgument::operator[]( Tint index ) const
{
  return GetElement( index );
}

inline Tstring TArgument::operator[]( const TOption& option ) const
{
  return GetParameter( option );
}

inline Tstring TArgument::operator[]( const Tstring& optionname ) const
{
  return GetParameter( optionname );
}

inline const Tstring& TArgument::GetUsage() const
{
  return theUsage;
}

inline Tvoid TArgument::SetUsage( const Tstring& usage )
{
  theUsage = usage;
  return;
}

#endif
