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

//////////////////////////////////////////////////////////////////////////////
//
//  MEnv
//
// It is a slightly changed version of TEnv. It logs all resources which are
// touched, so that you can print all untouched resources by
// PrintUntouched()
//
//////////////////////////////////////////////////////////////////////////////
#include "MEnv.h"

#include <Gtypes.h>
#include <TObjString.h>

#include <TAttText.h>
#include <TAttFill.h>
#include <TAttLine.h>
#include <TAttMarker.h>

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

ClassImp(MEnv);

using namespace std;

Int_t MEnv::GetValue(const char *name, Int_t dflt)
{
    if (!fChecked.FindObject(name))
        fChecked.Add(new TObjString(name));
    return TEnv::GetValue(name, dflt);
}

Double_t MEnv::GetValue(const char *name, Double_t dflt)
{
    if (!fChecked.FindObject(name))
        fChecked.Add(new TObjString(name));
    return TEnv::GetValue(name, dflt);
}

const char *MEnv::GetValue(const char *name, const char *dflt)
{
    if (!fChecked.FindObject(name))
        fChecked.Add(new TObjString(name));
    return TEnv::GetValue(name, dflt);
}

Int_t MEnv::GetColor(const char *name, Int_t dftl)
{
    TString str = GetValue(name, "");

    str = str.Strip(TString::kBoth);
    if (str.IsNull())
        return dftl;

    str.ToLower();

    switch (str.Hash())
    {
    case (unsigned)-1926423925/*2368543371*/: return kWhite;
    case 1814927399: return kBlack;
    case 7496964:    return kRed;
    case (unsigned)-1397860222/*2897107074*/: return kGreen;
    case 1702194402: return kBlue;
    case (unsigned)-1920149414/* 2374817882*/: return kYellow;
    case (unsigned)-1400748595/*2894218701*/: return kMagenta;
    case 1851881955: return kCyan;
    case 749623518: return 18; // grey1
    case 749623517: return 17; // grey2
    case 749623516: return 16; // grey3
    case 749623515: return 15; // grey4
    case 749623514: return 14; // grey5
    case 741234910: return 18; // gray1
    case 741234909: return 17; // gray2
    case 741234908: return 16; // gray3
    case 741234907: return 15; // gray4
    case 741234906: return 14; // gray5
    }
    return str.Atoi();
}

TString MEnv::Compile(TString str, const char *post) const
{
    if (!str.IsNull() && str[str.Length()-1]!='.')
        str += ".";

    str += post;

    return str;
}

void MEnv::GetAttLine(const char *name, TAttLine &line, TAttLine *dftl)
{
    const TString color = Compile(name, "LineColor");
    const TString style = Compile(name, "LineStyle");
    const TString width = Compile(name, "LineWidth");

    if (!dftl)
        dftl = &line;

    const Color_t col = GetColor(color, dftl->GetLineColor());
    const Style_t sty = GetValue(style, dftl->GetLineStyle());
    const Style_t wid = GetValue(width, dftl->GetLineWidth());

    line.SetLineColor(col);
    line.SetLineStyle(sty);
    line.SetLineWidth(wid);
}

void MEnv::GetAttText(const char *name, TAttText &text, TAttText *dftl)
{
   const TString color = Compile(name, "TextColor");
   const TString align = Compile(name, "TextAlign");
   const TString angle = Compile(name, "TextAngle");
   const TString font  = Compile(name, "TextFont");
   const TString size  = Compile(name, "TextSize");

    if (!dftl)
        dftl = &text;

    const Color_t col = GetColor(color, dftl->GetTextColor());
    const Short_t ali = GetValue(align, dftl->GetTextAlign());
    const Float_t ang = GetValue(angle, dftl->GetTextAngle());
    const Font_t  fon = GetValue(font,  dftl->GetTextFont());
    const Float_t siz = GetValue(size,  dftl->GetTextSize());

    text.SetTextColor(col);
    text.SetTextAlign(ali);
    text.SetTextAngle(ang);
    text.SetTextFont(fon);
    text.SetTextSize(siz);
}

void MEnv::GetAttFill(const char *name, TAttFill &fill, TAttFill *dftl)
{
    const TString color = Compile(name, "FillColor");
    const TString style = Compile(name, "FillStyle");

    if (!dftl)
        dftl = &fill;

    const Color_t col = GetColor(color, dftl->GetFillColor());
    const Style_t sty = GetValue(style, dftl->GetFillStyle());

    fill.SetFillColor(col);
    fill.SetFillStyle(sty);
}

void MEnv::GetAttMarker(const char *name, TAttMarker &marker, TAttMarker *dftl)
{
    const TString color = Compile(name, "MarkerColor");
    const TString style = Compile(name, "MarkerStyle");
    const TString size  = Compile(name, "MarkerSize");

    if (!dftl)
        dftl = &marker;

    const Color_t col = GetColor(color, dftl->GetMarkerColor());
    const Style_t sty = GetValue(style, dftl->GetMarkerStyle());
    const Size_t  siz = GetValue(size,  dftl->GetMarkerSize());

    marker.SetMarkerColor(col);
    marker.SetMarkerStyle(sty);
    marker.SetMarkerSize(siz);
}

void MEnv::GetAttributes(const char *name, TObject *obj, TObject *dftl)
{
    //TAttAxis         *line = dynamic_cast<TAttAxis*>(obj);
    //TAtt3D           *line = dynamic_cast<TAtt3D*>(obj);
    //TAttCanvas       *line = dynamic_cast<TAttCanvas*>(obj);
    //TAttFillCanvas   *line = dynamic_cast<TAttFillEitor*>(obj);
    //TAttLineCanvas   *line = dynamic_cast<TAttLineCanvas*>(obj);
    //TAttLineEditor   *line = dynamic_cast<TAttLineEditor*>(obj);
    //TAttMarkerCanvas *line = dynamic_cast<TAttMarkerCanvas*>(obj);
    //TAttMarkerEditor *line = dynamic_cast<TAttMarkerEditor*>(obj);
    //TAttPad          *line = dynamic_cast<TAttPad*>(obj);
    //TAttParticle     *line = dynamic_cast<TAttParticle*>(obj);
    //TAttTextCanvas   *line = dynamic_cast<TAttTextCanvas*>(obj);
    //TAttTextEditor   *line = dynamic_cast<TAttTextEditor*>(obj);

    TAttLine   *line = dynamic_cast<TAttLine*>(/*(TAttLine*)*/obj);
    TAttText   *text = dynamic_cast<TAttText*>(/*(TAttText*)*/obj);
    TAttFill   *fill = dynamic_cast<TAttFill*>(/*(TAttFill*)*/obj);
    TAttMarker *mark = dynamic_cast<TAttMarker*>(/*(TAttMarker*)*/obj);

    cout << line << " " << text << " " << fill << " " << mark << endl;

    if (line)
        GetAttLine(name, *line, dynamic_cast<TAttLine*>(/*(TAttLine*)*/dftl));
    if (text)
        GetAttText(name, *text, dynamic_cast<TAttText*>(/*(TAttText*)*/dftl));
    if (fill)
        GetAttFill(name, *fill, dynamic_cast<TAttFill*>(/*(TAttFill*)*/dftl));
    if (mark)
        GetAttMarker(name, *mark, dynamic_cast<TAttMarker*>(/*(TAttMarker*)*/dftl));
}

void MEnv::PrintUntouched() const
{
    int i=0;
    gLog << inf << flush;
    gLog.Separator("Untouched Resources");
    TIter Next(GetTable());
    TObject *o=0;
    while ((o=Next()))
        if (!fChecked.FindObject(o->GetName()))
        {
            gLog << warn << " - Resource " << o->GetName() << " not touched" << endl;
            i++;
        }
    if (i==0)
        gLog << inf << "None." << endl;
    else
        gLog << inf << i << " resources have not been touched." << endl;
}
