#include <TGeoManager.h>
#include <TGeoVolume.h>
#include <TObjArray.h>
#include <iostream>

//____________________________________________________________________	
Int_t CheckNodes(TGeoNode* node, const char* name, Int_t& lvl)
{
  // If there's no node here. 
  if (!node) return -1;
  // Check if it this one 
  TString sname(name);
  if (sname == node->GetName()) return lvl;

  // Check if the node is an immediate daugther 
  TObjArray* nodes = node->GetNodes();
  if (!nodes) return -1;
  // Increase the level, and search immediate sub nodes. 
  lvl++;
  TGeoNode*  found = static_cast<TGeoNode*>(nodes->FindObject(name));
  if (found) return lvl;

  // Check the sub node, if any of their sub-nodes match.
  for (Int_t i = 0; i < nodes->GetEntries(); i++) {
    TGeoNode* sub = static_cast<TGeoNode*>(nodes->At(i));
    if (!sub) continue;
    // Recurive check 
    if (CheckNodes(sub, name, lvl) >= 0) return lvl;
  }
  // If not found, decrease the level 
  lvl--;
  return -1;
}
//____________________________________________________________________	
Int_t 
FindNodeDepth(const char* name) 
{
  TGeoNode*  node  = gGeoManager->GetTopNode();
  Int_t lvl = 0;
  return CheckNodes(node, name, lvl);
}
//____________________________________________________________________	
Int_t CheckVolumes(TGeoVolume* vol, const char* name, Int_t& lvl) 
{
  // If there's no node here. 
  if (!vol) return -1;
  // Check if it this one 
  TString sname(name);
  if (sname == vol->GetName()) return lvl;

  // Check if the node is an immediate daugther 
  TObjArray* nodes = vol->GetNodes();
  if (!nodes) return -1;
  
  // Increase level
  lvl++;
  // Check the sub node, if any of their sub-nodes match.
  for (Int_t i = 0; i < nodes->GetEntries(); i++) {
    TGeoNode*   node = static_cast<TGeoNode*>(nodes->At(i));
    if (!node) continue;
    TGeoVolume* sub  = node->GetVolume();
    if (!sub) continue;
    if (sname == sub->GetName()) return lvl;
    // Recurive check 
    if (CheckVolumes(sub, name, lvl) >= 0) return lvl;
  }
  // If not found, decrease the level 
  lvl--;
  return -1;
}
//____________________________________________________________________	
Int_t 
FindDepth(const char* name) 
{
  TGeoVolume*  top  = gGeoManager->GetTopVolume();
  Int_t lvl = 0;
  return CheckVolumes(top, name, lvl);
}

//____________________________________________________________________	
Int_t CheckNodePaths(TGeoNode* node, const char* name, Int_t& lvl, 
		     TString& path)
{
  // If there's no node here. 
  if (!node) return -1;
  // Check if it this one 
  TString sname(name);
  if (sname == node->GetName()) return lvl;
  // Check if the node is an immediate daugther 
  TObjArray* nodes = node->GetNodes();
  if (!nodes) return -1;
  // Increase the level, and search immediate sub nodes. 
  lvl++;
  TGeoNode*  found = static_cast<TGeoNode*>(nodes->FindObject(name));
  if (found) {
    path = Form("%s/%s", node->GetName(), name);
    return lvl;
  }

  // Check the sub node, if any of their sub-nodes match.
  for (Int_t i = 0; i < nodes->GetEntries(); i++) {
    TGeoNode* sub = static_cast<TGeoNode*>(nodes->At(i));
    if (!sub) continue;
    // Recurive check 
    if (CheckNodePaths(sub, name, lvl, path) >= 0) { 
      path.Prepend(Form("%s/", node->GetName()));
      return lvl;
    }
  }
  // If not found, decrease the level 
  lvl--;
  return -1;
}
//____________________________________________________________________	
TString
FindPath(const char* name) 
{
  TString path;
  TGeoNode*  node  = gGeoManager->GetTopNode();
  Int_t lvl = 0;
  CheckNodePaths(node, name, lvl, path);
  return path;
}
//____________________________________________________________________	
//
// EOF
//



