/** \class HistMan
 *
 * \brief manage histograms.
 *
 * HistMan is a class that simplifies working with histograms.  It
 * provides a simple HBOOK like interface to booking and filling
 * histograms.  It also handles organizing them in a hierarchy based
 * on named paths very much like the Unix filesystem.  Finally it
 * handles file I/O in a way that preserves this organization.
 *
 * While in memory, the hierarchy is maintained with TFolders and on
 * disk in TDirectories.  The hierarchy can either be owned by the
 * HistMan instance, and thus have the same persistency as the
 * instance itself or it can be owned by ROOT.  This latter case is
 * the most useful one as it lets one create and destroy HistMan
 * instance at will while the hierarchy is built up.
 *
 * Regardless of the memory management, a HistMan instance is
 * logically rooted at some point of the hierarchy.  That is, any
 * instance can only know about histograms and sub hierarchies that
 * are on the branch on which the instance sits. 
 *
 */
#ifndef HISTMAN_HISTMAN_H
#define HISTMAN_HISTMAN_H

#include <TFolder.h>
#include <TH1.h>

#include <HistMan/RootHists.h>	// needed for inside Cint.cc file

class TFile;

// Helper. Acts like "mkdir -p" to add a full path with 1 or more
// subdirectories.  Return last folder.  This should be in TFolder....
TFolder& mkdir_p(TFolder& folder, const char* path);

class HistMan {
    TFolder* fFolder;
    bool fOwn;


public:
    /// Create a HistMan with a TFolder created in the given base
    /// directory.  This implies that ownership is given to gROOT's
    /// memory.  Histograms will be visible in 
    /// "//root/ROOT memory/HistMan/base_directory/"
    /// This is the most typical way to use HistMan.
    HistMan(const char* base_directory = "");

    /// Create a Histman and try to attach the "HistMan" directory in
    /// the given file (such as would exist if the file was created by
    /// HistMan::WriteOut()).  If fail, will act like Histman("")
    /// above.  If successfull, the file is still used to store the
    /// histograms so must be kept open while they are to be used.
    HistMan(TFile& file);

    /// Create a HistMan.  If "own" is true the folder is deleted
    /// along with this object.  This will root the hierarchy in a
    /// uniquely named root folder (like HistFolderXXX).
    HistMan(TFolder* folder, bool own=true);

    /// Destructor deletes folder if owned.
    ~HistMan();

    /// Get the base HistMan.  It will will create if not yet existing
    TFolder& BaseFolder();

    /// Register the base folder with gROOT, gives up ownership and
    /// folder becomes visible in //root/ROOT Memory/HistMan in a
    /// TBrowser.  This is only needed if the instance is created with
    /// HistMan(TFolder*,bool).
    void RegisterWithRoot();

    /// Write hierachy of histograms to given TFile.
    void WriteOut(TFile& opened_file);

    /// Write out hierachy to recreated file of given name. 
    void WriteOut(const char* filename);

    /// Adopt an already created histogram (or really any TObject),
    /// return NULL (and delete hist) if a histogram with same name as
    /// "hist" at path already exists, otherwise return the object.
    /// An empty or NULL string can be passed for the path to place
    /// the object in HistMan instance's top level folder.
    TObject* Adopt(const char* path, TObject* hist);

    /// Try to find histogram of with pathname="path/name" in this
    /// instances branch of the hierarchy.  Path is relative to this
    /// objects TFolder.  Returns NULL if histogram does not exist or
    /// if there is a type mismatch.
    template<class THType>
    THType* Get(const char* pathname) {
        return dynamic_cast<THType*>(this->GetObject(pathname));
    }
        

    /// Get the object at the given path
    TObject* GetObject(const char* pathname);

    /// A simplified histogram API is exported with the methods below.

    /// Book 1D histograms of type THType.  Return pointer to created
    /// histogram (HistMan retains ownership) or 0 if "path/name"
    /// conflicts with previously existing histogram.
    template<class THType>
    THType* Book(const char* name, const char* title,
                 int nbinsx, Axis_t xmin, Axis_t xmax,
                 const char* path=".", Bool_t sumw2=kFALSE) {
        THType* h = new THType(name,title,nbinsx,xmin,xmax);
        if ( sumw2 ) {
            h->Sumw2();
        }
        TObject* o = Adopt(path, h);
        return dynamic_cast<THType*>(o);
    }

    /// Book 2D histograms of type THType.  Return pointer to created
    /// histogram (HistMan retains ownership) or 0 if "path/name"
    /// conflicts with previously existing histogram.
    template<class THType>
    THType* Book(const char* name, const char* title,
                 int nbinsx, Axis_t xmin, Axis_t xmax,
                 int nbinsy, Axis_t ymin, Axis_t ymax,
                 const char* path=".", Bool_t sumw2=kFALSE) {
        THType* h = new THType(name,title,nbinsx,xmin,xmax, nbinsy,ymin,ymax);
        if ( sumw2 ) {
            h->Sumw2();
        }
        TObject* o = Adopt(path, h);
        return dynamic_cast<THType*>(o);
    }

    /// Lookup a 1D histogram by pathname="path/name" and Fill() it.
    /// If lookup or any casting fails, false is returned and an error
    /// message is printed at Msg level Warning.
    bool Fill1d(const char* pathname, Axis_t x, Stat_t w=1.0);

    /// Lookup a 2D histogram by pathname="path/name" and Fill() it.
    /// If lookup or any casting fails, false is returned and an error
    /// message is printed at Msg level Warning.
    bool Fill2d(const char* pathname, Axis_t x, Axis_t w, Stat_t w=1.0);

};



#endif  // HISTMAN_HISTMAN_H
