/* ======================================================================== *\
!
! *
! * 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 03/2004 <mailto:tbretz@astro.uni-wuerzburg.de>
!
!   Copyright: MAGIC Software Development, 2000-2004
!
!
\* ======================================================================== */

//////////////////////////////////////////////////////////////////////////////
//
//  MStatusArray
//
//  Helper class for MStatusDisplay
//
//////////////////////////////////////////////////////////////////////////////
#include "MStatusArray.h"

#include <TClass.h>
#include <TCanvas.h>

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

#include "MStatusDisplay.h"

ClassImp(MStatusArray);

using namespace std;

TObject *MStatusArray::DisplayIn(Option_t *o) const
{
    MStatusDisplay *d = 0;
    if (TString(o).IsNull())
        d = new MStatusDisplay;

    if (!d)
        d = (MStatusDisplay*)gROOT->GetListOfSpecials()->FindObject(o);

    if (!d)
        return 0;

    if (d->Display(*this))
        return d;

    delete d;
    return 0;
}

void MStatusArray::DisplayIn(MStatusDisplay &d, const char *tab) const
{
    d.Display(*this, tab);
}

TObject *MStatusArray::FindObjectInPad(TVirtualPad *pad, const char *object, TClass *cls) const
{
    TObject *o = pad->FindObject(object);
    if (o && o->InheritsFrom(cls))
        return o;

    TIter Next(pad->GetListOfPrimitives());
    while ((o=Next()))
    {
        if (o==pad || !o->InheritsFrom(TVirtualPad::Class()))
            continue;

        if ((o = FindObjectInPad((TVirtualPad*)o, object, cls)))
            if (o->InheritsFrom(cls))
                return o;
    }
    return 0;
}

// FIXME: Move to a general class MMARS (TROOT) and unify with MParContainer
TClass *MStatusArray::GetClass(const char *name) const
{
    TClass *cls = gROOT->GetClass(name);
    Int_t rc = 0;
    if (!cls)
        rc =1;
    else
    {
        if (!cls->Property())
            rc = 5;
        if (!cls->Size())
            rc = 4;
        if (!cls->IsLoaded())
            rc = 3;
        if (!cls->HasDefaultConstructor())
            rc = 2;
    }

    if (rc==0)
        return cls;

    gLog << err << dbginf << "Class '" << name << "' not in dictionary: ";
    switch (rc)
    {
    case 1:
        gLog << "gROOT->GetClass() returned NULL." << endl;
        return NULL;
    case 2:
        gLog << "no default constructor." << endl;
        return NULL;
    case 3:
        gLog << "not loaded." << endl;
        return NULL;
    case 4:
        gLog << "zero size." << endl;
        return NULL;
    case 5:
        gLog << "no property." << endl;
        return NULL;
    }

    gLog << "THIS SHOULD NEVER HAPPEN!" << endl;

    return 0;
}

TCanvas *MStatusArray::FindCanvas(const char *name) const
{
    TObject *o = TObjArray::FindObject(name);
    if (!o)
        return 0;

    return o->InheritsFrom(TCanvas::Class()) ? (TCanvas*)o : 0;
}


TObject *MStatusArray::FindObjectInCanvas(const char *object, const char *base, const char *canvas) const
{
    TClass *cls = GetClass(base);
    if (!cls)
        return 0;

    TCanvas *c = canvas ? FindCanvas(canvas) : 0;
    if (canvas)
    {
        if (!c)
        {
            gLog << warn << "Canvas '" << canvas << "' not found..." << endl;
            return 0;
        }

        TObject *o = FindObjectInPad(c, object, cls);
        if (!o)
        {
            gLog << warn << "Object '" << object << "' [" << base << "] not found in canvas '" << canvas << "'..." << endl;
            return 0;
        }

        return o; //o->InheritsFrom(cls) ? o : 0;
    }

    TObject *o=0;
    TIter Next(this);
    while ((o=Next()))
    {
        if (!o->InheritsFrom(TVirtualPad::Class()))
            continue;

        if ((o=FindObjectInPad((TVirtualPad*)c, object, cls)))
            return o;
    }

    gLog << warn << "Object '" << object << "' [" << base << "] not found in canvas '" << canvas << "'..." << endl;
    return NULL;
}

TObject *MStatusArray::FindObjectInCanvas(const char *object, const char *canvas) const
{
    return FindObjectInCanvas(object, object, canvas);
}

TObject *MStatusArray::FindObject(const char *object, const char *base) const
{
    return FindObjectInCanvas(object, base, 0);
}

TObject *MStatusArray::FindObject(const char *object) const
{
    return FindObjectInCanvas(object, object, 0);
}
