/* ======================================================================== *\
!
! *
! * This file is part of MARS, the MAGIC Analysis and Reconstruction
! * Software. It is distributed to you in the hope that it can be a useful
! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
! * It is distributed WITHOUT ANY WARRANTY.
! *
! * Permission to use, copy, modify and distribute this software and its
! * documentation for any purpose is hereby granted without fee,
! * provided that the above copyright notice appear in all copies and
! * that both that copyright notice and this permission notice appear
! * in supporting documentation. It is provided "as is" without express
! * or implied warranty.
! *
!
!
!   Author(s): Thomas Bretz, 7/2003 <mailto:tbretz@astro.uni-wuerzburg.de>
!
!   Copyright: MAGIC Software Development, 2003
!
!
\* ======================================================================== */


//////////////////////////////////////////////////////////////////////////////
//
// MArgs
//
//////////////////////////////////////////////////////////////////////////////
#include "MArgs.h"

#include <stdlib.h>

#include "MLog.h"
#include "MLogManip.h"

ClassImp(MArgsEntry);
ClassImp(MArgs);

using namespace std;

void MArgsEntry::Print(const Option_t *o) const
{
    gLog << all << *this << endl;
}

MArgs::MArgs(int argc, const char **argv) : fArgc(argc)
{
    fName = argv[0];

    fArgv = new TList;
    fArgv->SetOwner();

    for (int i=1; i<argc; i++)
    {
        MArgsEntry &o = *new MArgsEntry(argv[i]);
        dynamic_cast<TString&>(o) = o.Strip(TString::kBoth);
        fArgv->Add(&o);
    }
}

MArgs::~MArgs()
{
    delete fArgv;
}

void MArgs::Print(const Option_t *o) const
{
    gLog << all << underline << fName << ":" << endl;
    fArgv->Print();
}

Int_t MArgs::GetInt(const TString name) const
{
    return atoi(GetString(name));
}

Double_t MArgs::GetFloat(const TString name) const
{
    return atof(GetString(name));
}

TString MArgs::GetString(const TString name) const
{
    TIter Next(fArgv);
    TString *s = NULL;
    while ((s=dynamic_cast<TString*>(Next())))
        if (s->BeginsWith(name))
            return s->Data()+s->Index(name)+name.Length();
    return 0;
}

Int_t MArgs::GetIntAndRemove(const TString name)
{
    return atoi(GetStringAndRemove(name));
}

Double_t MArgs::GetFloatAndRemove(const TString name)
{
    return atof(GetStringAndRemove(name));
}

TString MArgs::GetStringAndRemove(const TString n)
{
    const TString name = n.Strip(TString::kBoth);

    TIter Next(fArgv);
    TString *s = NULL;
    while ((s=dynamic_cast<TString*>(Next())))
        if (s->BeginsWith(name))
        {
            TString str = s->Data()+s->Index(name)+name.Length();
            delete fArgv->Remove(dynamic_cast<TObject*>(s));
            return str;
        }
    return 0;
}

Int_t MArgs::GetArgumentInt(Int_t i) const
{
    return atoi(GetArgumentStr(i));
}

Float_t MArgs::GetArgumentFloat(Int_t i) const
{
    return atof(GetArgumentStr(i));
}

TString MArgs::GetArgumentStr(Int_t i) const
{
    Int_t num = 0;

    TIter Next(fArgv);
    TString *s = NULL;
    while ((s=dynamic_cast<TString*>(Next())))
    {
        if (s->BeginsWith("-"))
            continue;

        if (i==num++)
            return *s;
    }

    return "";
}

Int_t MArgs::GetNumArguments() const
{
    Int_t num = 0;

    TIter Next(fArgv);
    TString *s = NULL;
    while ((s=dynamic_cast<TString*>(Next())))
        if (!s->BeginsWith("-"))
            num++;

    return num;
}

Bool_t MArgs::Has(const TString n) const
{
    const TString name = n.Strip(TString::kBoth);

    TIter Next(fArgv);
    TString *s = NULL;
    while ((s=dynamic_cast<TString*>(Next())))
        if (s->BeginsWith(name))
            return kTRUE;
    return kFALSE;
}

Bool_t MArgs::HasOption(const TString n) const
{
    const TString name = n.Strip(TString::kBoth);

    TIter Next(fArgv);
    TString *s = NULL;
    while ((s=dynamic_cast<TString*>(Next())))
        if (s->BeginsWith(name) && s->Length()>name.Length())
            return kTRUE;
    return kFALSE;
}
