/* ======================================================================== *\
!
! *
! * 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  01/2002 <mailto:tbretz@uni-sw.gwdg.de>
!
!   Copyright: MAGIC Software Development, 2000-2002
!
!
\* ======================================================================== */

/////////////////////////////////////////////////////////////////////////////
//
// MFDataMember                                                              
//
// With this filter you can filter in all variables from Mars parameter
// containers.
//
// In the constructor you can give the filter variable, like
//   "MHillas.fLength"
// Where MHillas is the name of the parameter container in the parameter
// list and fLength is the name of the data member which should be used
// for the filter rule. If the name of the container is use specified
// (MyHillas) the name to give would be:
//   "MyHillas.fLength"
//
// For example:
//   MFDataMember filter("MHillas.fLength", '<', 150);
//
/////////////////////////////////////////////////////////////////////////////

#include "MFDataMember.h"

#include <TMethodCall.h>

#include "MParList.h"

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

ClassImp(MFDataMember);

// --------------------------------------------------------------------------
//
MFDataMember::MFDataMember(const char *member, const char type, const Double_t val,
                           const char *name, const char *title)
{
    fName  = name  ? name  : "MFDataMember";
    fTitle = title ? title : "Filter using any data member of a class";

    fFilterType = (type=='<' ? kELowerThan : kEGreaterThan);

    if (type!='<' && type!='>')
        *fLog << warn << dbginf << "Warning: Neither '<' nor '>' specified... using '>'." << endl;

    fValue = val;

    fDataMember = member;

    AddToBranchList(fDataMember);
}

// --------------------------------------------------------------------------
//
Bool_t MFDataMember::PreProcess(MParList *plist)
{
    TString cname(fDataMember);
    TString mname(fDataMember);

    const char *dot = strrchr(cname, '.');

    if (dot)
    {
        const int pos = dot-cname;

        cname.Remove(pos);
        mname.Remove(0, pos+1);
    }

    fObject = (MParContainer*)plist->FindObject(cname);
    if (!fObject)
    {
        *fLog << err << "Object '" << cname << "' not in parameter list... aborting." << endl;
        return kFALSE;
    }

    fMethodCall = fObject->GetterMethod(mname);

    return fMethodCall ? kTRUE : kFALSE;
}

// --------------------------------------------------------------------------
//
Bool_t MFDataMember::Process()
{
    Double_t v;
    switch (fMethodCall->ReturnType())
    {
    case TMethodCall::kLong:
        Long_t l;
        fMethodCall->Execute(fObject, l);
        v = l;
        return kTRUE;

    case TMethodCall::kDouble:
        fMethodCall->Execute(fObject, v);
        return kTRUE;

    default:
        *fLog << err << "DataMember " << fDataMember << " of ";
        *fLog << fObject->GetName() << " neither int nor float... abort." << endl;
        return kFALSE;
    }

    switch (fFilterType)
    {
    case kELowerThan:
        fResult = (v < fValue);
        break;
    case kEGreaterThan:
        fResult = (v > fValue);
        break;
    }

    return kTRUE;
}

void MFDataMember::Print(Option_t *) const
{
    *fLog << fDataMember << (fFilterType==kELowerThan?"<":">");
    *fLog << fValue << flush;
}
