#include "QFramework/TQPathManager.h"

#include <algorithm>
#include <cstdio>
#include <string>
#include <vector>
#include <filesystem>

#include "QFramework/TQUtils.h"
#include "QFramework/TQStringUtils.h"

// #define _DEBUG_

#include "QFramework/TQLibrary.h"

#include "TString.h"
#include "TSystem.h"

ClassImp(TQPathManager)

//@env: [CAF_USE_TEMP_DIR, CAF_USE_LOCAL_STORAGE] can be used to disable the use of (temporary) 
//@env  node local storage for outputs. If set to "no", "false", or "0"
//@env  outputs will be written directly to their target destination
//@env  (can reduce performance but may be needed on some clusters) 
//@env  CAFUSETEMPDIR takes precedence over CAFUSELOCALSTORAGE in case both are set
const bool TQPathManager::gUseTemporaryStorageDefault = 
  TQUtils::readEnvVarValueBool("CAF_USE_TEMP_DIR", 
    TQUtils::readEnvVarValueBool("CAF_USE_LOCAL_STORAGE", true)
  );

// Index used to uniquely identify all local files
int TQPathManager::filenameIndex = 0;
TQPathManager TQPathManager::gPathManager; //MUST be after initialization of gUseTemporaryStrageDefault!
bool TQPathManager::gPathManagerExists = false;


////////////////////// static methods //////////////////////


std::string TQPathManager::findFileFromEnvVar(const TString& filename, const std::string& envVar, bool printWarnings){
  return findFileFromEnvVar_internal(filename, envVar, printWarnings, true);
}

std::string TQPathManager::findFileFromEnvVarWithoutExecDir(const TString& filename, const std::string& envVar, bool printWarnings){
  return findFileFromEnvVar_internal(filename, envVar, printWarnings, false);
}

std::string TQPathManager::findFileFromEnvVar_internal(const TString& filename, const std::string& envVar, bool printWarnings, bool searchExecutionDir){
  // Take value of envVar and use it to call findFileFromList

  std::string searchPathList = TQUtils::readEnvVarValue(envVar);
  if (searchPathList == ""){
    DEBUGclass("Calling findFileFromList with an empty searchPathList since the environment variable %s was not found.", envVar.c_str());
  }

  std::string filePath = TQPathManager::findFileFromList_internal(filename, searchPathList, printWarnings, searchExecutionDir);
  if ((searchPathList == "") && (filePath == "")){
    TString message = TQStringUtils::format("The environment variable %s is not defined. Is this the reason why the file %s could not be found?", envVar.c_str(), filename.Data());
    if (printWarnings) {WARNclass(message);}
    else {DEBUGclass(message);}
  }

  return filePath;
}

std::string TQPathManager::findFileFromList(TString filename, const std::string& searchPathList, bool printWarnings){
  return findFileFromList_internal(filename, searchPathList, printWarnings, true);
}

std::string TQPathManager::findFileFromListWithoutExecDir(TString filename, const std::string& searchPathList, bool printWarnings){
  return findFileFromList_internal(filename, searchPathList, printWarnings, false);
}

void TQPathManager::setWorkingDirectory(TString dir){
  // changes the working directory to the given path
  // WARNING: this change affects the reading and writing location of files
  //          in many places, some of which the person calling this function
  //          (i.e., you) might not be aware of. Only call this function if
  //          you know *exactly* what you are doing and why!
  DEBUGclass("working directory changed from '%s' to '%s'",this->pwd.Data(),dir.Data());
  this->pwd = dir;
}

std::string TQPathManager::findFileFromList_internal(TString filename, const std::string& searchPathList, bool printWarnings, bool searchExecutionDir){
  // Largely copied from Athena's more sophisticated PathResolver
  // 1. if filename is given as absolute path,
  // 1.1 if it exists, return absolute path
  // 1.2 if it doesn't exist, return ""
  // 2. if filename is local file and searchExecutionDir, return absolute path
  // 3. if filename is in searchPathList, return absolute path
  // 4. otherwise return ""

  // Remove leading and trailing spaces
  filename = TQStringUtils::trim(filename);

  if (searchPathList == "") {DEBUGclass("Trying to find %s locally.", filename.Data());}
  else {DEBUGclass("Trying to find %s in %s.", filename.Data(), searchPathList.c_str());}

  if (filename == ""){
    DEBUGclass("The passed argument filename is empty. Exiting the method.");
    return "";
  }

  TString localDir = gSystem->pwd();
  TString localPath = TQFolder::concatPaths(localDir, filename);

  // Check if file is given as an absolute path and if it is a regular file
  // (as opposed to a directory)
  if (gSystem->IsAbsoluteFileName(filename.Data())){
    if (TQUtils::fileExists(filename)){
      std::string totalPath = filename.Data();
      DEBUGclass("Found absolute path: %s. Not resolving.", filename.Data());
      return totalPath;
    }
    TString message = TQStringUtils::format("It looks like %s is an absolute path, but there is no such file (is it maybe a directory?). Exiting this method.", filename.Data());
    if (printWarnings) {WARNclass(message.Data());}
    else {DEBUGclass(message.Data());}
    return "";
  }
  // Check if filename matches local file in the execution directory
  if ((searchExecutionDir) && (TQUtils::fileExists(localPath))){
    std::string totalPath = localPath.Data();
    DEBUGclass("Found %s here: %s", filename.Data(), totalPath.c_str());
    return totalPath;
  }
  // Loop over all directories in searchPathList and look for filename
  std::vector< TString > searchPathVector;
  searchPathVector = TQStringUtils::split(searchPathList, ":");
  for (auto& searchPath:searchPathVector){
    TString filePath = TQFolder::concatPaths(searchPath, filename);
    if (TQUtils::fileExists(filePath)){
      std::string totalPath = filePath.Data();
      DEBUGclass("Found %s here: %s", filename.Data(), totalPath.c_str());
      return totalPath;
    }
  }
  TString message = TQStringUtils::format("The file %s could not be found.", filename.Data());
  if (printWarnings) {WARNclass(message.Data());}
  else {DEBUGclass(message.Data());}
  return "";
}

TQPathManager* TQPathManager::getPathManager(){
  if (TQPathManager::gPathManagerExists)
    return &gPathManager;
  return nullptr;
}


////////////////////// public methods //////////////////////


bool TQPathManager::getUseTemporaryStorage() const {
  return this->useTemporaryStorage;
}

void TQPathManager::setUseTemporaryStorage(bool useTemporaryStorage){
  if ((this->pathsRequested) and (this->useTemporaryStorage != useTemporaryStorage))
    WARNclass("Changing the variable useTemporaryStorage after path names have been requested might cause problems. Especially the method \"TQPathManager::deleteLocalFile(...)\" will not work reliably. Try to avoid calling this method late during runtime.");
  this->useTemporaryStorage = useTemporaryStorage;
}

TString TQPathManager::getLocalDirectory() const {
  return this->localDirectory;
}

bool TQPathManager::setLocalDirectory(TString localDirectory){
  if (!localDirectory.EndsWith("/"))
    localDirectory.Append("/");

  if ((this->pathsRequested) and (this->localDirectory != localDirectory))
    WARNclass("Changing the variable localDirectory after path names have been requested might cause problems. Especially the method \"TQPathManager::deleteLocalFile(...)\" will not work reliably. Try to avoid calling this method late during runtime.");

  // Create it if it does not exist yet.
  if (!TQUtils::ensureDirectory(localDirectory)){
    WARNclass("Local directory %s could not be created. Do you have the necessary rights? Not setting localDirectory.", localDirectory.Data());
    return false;
  }

  this->localDirectory = localDirectory;
  if (this->useTemporaryStorage){
    DEBUGclass("TQPathManager uses the local directory %s for temporary storage.", localDirectory.Data());
  }
  return true;
}

void TQPathManager::setVerbose(bool verbose){
  this->verbose = verbose;
}

void TQPathManager::registerLocalPath(TString targetFile){
  targetFile = TQStringUtils::trim(targetFile);
  if (!isInLocalPaths_target(targetFile)){
    WARNclass("You request that even getTargetPath(%s) return a local path. Please call this method only after you first retrieve this local path. Otherwise it has no effect.", targetFile.Data());
    return;
  }
  alwaysReturnLocalPath[targetFile] = true;
}

void TQPathManager::unregisterLocalPath(TString targetFile){
  targetFile = TQStringUtils::trim(targetFile);
  if (!isInLocalPaths_target(targetFile)){
    WARNclass("You request that getTargetPath(%s) not return a local path. Since no local path has ever been created, there should be no reason to call this method. Please check your code.", targetFile.Data());
    return;
  }
  if (!alwaysReturnLocalPath[targetFile]){
    DEBUGclass("alwaysReturnLocalPath[%s] is already false", targetFile.Data());
    return;
  }
  alwaysReturnLocalPath[targetFile] = false;
}

std::string TQPathManager::getTargetPath(TString targetFile, bool printWarnings){
  gSystem->ExpandPathName(targetFile);
  targetFile = TQStringUtils::trim(targetFile);

  if (isInLocalPaths_target(targetFile)){
    if (alwaysReturnLocalPath[targetFile]){
      DEBUGclass("Returning local path, because alwaysReturnLocalPath[%s] == true", targetFile.Data());
      return getLocalPath(targetFile);
    }
    else if (printWarnings){
      WARNclass("You are requesting the target path for a file that is already assigned temporary storage. Make sure that you don't copy files over.");
    }
  }
  TString targetPath = getTargetPathName(targetFile);
  DEBUGclass("Target path found: %s.", targetPath.Data());

  ////////////////////////////
  if (targetPath.BeginsWith("//")){
    ERRORclass("Congratulations: you just found a bug! Please post the following lines starting with ERROR on this website: https://gitlab.cern.ch/atlas-caf/CAFCore/issues/54. If possible, please also tell us your current commit of CAFCore (find it out by going into your CAFCore directory and typing \"git rev-parse HEAD\").");
    ERRORclass("$CAFOUTPUTDIR = %s", TQUtils::readEnvVarValue("CAFOUTPUTDIR").c_str());
    ERRORclass("this->pwd = %s", this->pwd.Data());
    ERRORclass("gSystem->pwd() = %s",  gSystem->pwd());
    ERRORclass("$PWD = %s", TQUtils::readEnvVarValue("PWD").c_str());
    ERRORclass("targetPath = %s", targetPath.Data());
    ERRORclass("this->useTemporaryStorage = %s", this->useTemporaryStorage ? "true" : "false");
    ERRORclass("this->filenameIndex = %i", this->filenameIndex);
    ERRORclass("this->pathsRequested = %s", this->pathsRequested ? "true" : "false");
    targetPath = targetPath.Replace(0, 1, "", 0);
    ERRORclass("Trying to copy your output file to %s. If this does not look correct, please log out of the current shell and log back in to temporarily fix this error.", targetPath.Data());
  }
  ////////////////////////////

  if (!isInTargetPaths(targetPath))
    targetPaths.push_back(targetPath);
  this->pathsRequested = true;
  return targetPath.Data();
}


std::string TQPathManager::getLocalPath(TString filename){
  // 1. If temporary storage is disabled, return target path.
  // 2. If target filename is on record, return corresponding local filename.
  // 3. If target filename does not have a local equivalent, create the file
  //    and return the its path.
  //
  // Local files are saved in
  // "/tmp/<username>/<processNumber>_<filenameIndex>_<filename>".

  if (!this->useTemporaryStorage){
    DEBUGclass("You have temporary storage disabled. Return target path instead of local path.");
    return this->getTargetPath(filename);
  }

  // Remove leading and trailing spaces
  filename = TQStringUtils::trim(filename);

  // If file is already on record, return the corresponding local filename.
  if (this->isInLocalPaths_target(filename)){
    DEBUGclass("A local file for %s does already exist at %s.", filename.Data(), localPaths.at(filename).Data());
    return localPaths.at(filename).Data();
  }
  if (this->isInTargetPaths(this->getTargetPathName(filename))){
    WARNclass("You are requesting a local path for a file that a target path has been requested for. This file might copy another one over.");
  }
  if (this->isInLocalPaths_local(TQFolder::concatPaths(this->localDirectory, filename))){
    // This warning does not work if localDirectory is changed during runtime.
    WARNclass("You are trying to get a local file for a local file. This doesn't make much sense. Continuing anyway.");
  }

  // Local file needs to be created. Build the filename.
  int extensionPos = TQStringUtils::rfind(filename,".");
  TString extension = "";
  if (extensionPos != kNPOS) extension = filename(extensionPos,filename.Length()); //if it seems like there is a file name extension, save it and re-apply it after the hashing.
  TString localFilename = std::to_string(::getpid()) + "_" + std::to_string(TQPathManager::filenameIndex++) + "_" + std::to_string(filename.Hash()) + extension;
  TString localPath = TQFolder::concatPaths(this->localDirectory, localFilename);

  if (!TQUtils::ensureDirectoryForFile(localPath)){
    WARNclass("Cannot create directory for local file %s. Use global storage instead and return target path.", localPath.Data());
    return this->getTargetPath(filename);
  }

  localPaths[filename] = localPath;
  alwaysReturnLocalPath[filename] = false;
  DEBUGclass("Assigned local file %s to target file %s.", localPath.Data(), filename.Data());
  this->pathsRequested = true;
  return localPath.Data();
}

std::string TQPathManager::findConfigPath(TString filename, bool errorMessageIfNotFound, bool searchExecutionDir){
  // Filenames with TQFolder syntax e.g. folder.root:objectinside>>::label are supported
  // in these cases, only folder.root will be used for finding the config
  // and the absolute path including :objectinside>>::label will be returned.
  // You can ignore looking for configs in the execution directory with
  // setting ignoreExecutionDirectory to true.

  if (filename == "") {
    WARNclass("Cannot find config from an empty string! Returning empty string.");
    return "";
  }

  std::vector<TString> splittedFileName = TQStringUtils::split(filename, ".root:");
  TString filenameBase;
  TString stringTail = "";
  if (splittedFileName.size() == 2) {
    filenameBase = TQStringUtils::concat(splittedFileName[0],".root");
    stringTail = TQStringUtils::concat(":", splittedFileName[1]);
  } else if (splittedFileName.size() ==1) {
    filenameBase = filename;
  } else {
    ERRORclass("Something odd happened. You are trying to find the path for the config file '%s' and is seems to have two times the identifier '.root:' in it. This is not supported, please check your code!", filename.Data());
  }
  //@env: [CAFANALYSISSHARE] Path to the "share" directory of the analysis package. If paths to config files,... 
  //@env are given as relative paths they will be searched for inside this directory unless a file with the given
  //@env relative paths exists relative to the current working directory.
  TString filePath = TQPathManager::findFileFromEnvVar_internal(filenameBase, "CAFANALYSISSHARE", true, searchExecutionDir);
  if (filePath == "" && errorMessageIfNotFound && TQUtils::readEnvVarValue("CAFANALYSISSHARE") == "") {
    WARNclass("Did you forget to set the environment variable 'CAFANALYSISSHARE' in your analysis package?");
  }

  TString returnFileName = filePath+stringTail;
  return returnFileName.Data();
}

bool TQPathManager::deleteLocalFile(TString filename){
  // 1. If temporary storage is disabled,
  // 1.1 if target path is on record, delete it instead of local path and return true,
  // 1.2 else return false
  // 2. If file is not on record, return false.
  // 3. Otherwise delete the file, erase the entry from localPaths and return true.
  //
  // Returns true if the file is on record (either in local or target location),
  // otherwise returns false. This does not necessarily say that a file has been
  // deleted.
  //
  // This method does not work properly if the variables useTemporaryStorage or
  // localDirectory are changed after paths have been requested.


  // Remove leading and trailing spaces
  filename = TQStringUtils::trim(filename);
  TString pathToDelete = "";

  // Check if temporary storage is enabled
  if (!this->useTemporaryStorage){
    DEBUGclass("You have temporary storage disabled. Deleting target file instead of local file.");
    pathToDelete = this->getTargetPathName(filename);
    if (isInTargetPaths(pathToDelete))
      this->deleteTargetPathEntry(pathToDelete);
  }
  else{
    // If temporary storage is enabled, check if there is a file to delete.
    // If not, return false.
    if (!this->isInLocalPaths_target(filename)){
      DEBUGclass("The file %s does not have a local file. Cannot delete it.", filename.Data());
      return false;
    }
    pathToDelete = localPaths.at(filename);
    // Remove the entry from localPaths.
    localPaths.erase(filename);
    alwaysReturnLocalPath.erase(filename);
    DEBUGclass("Deleted the database entry corresponding to %s.", filename.Data());
  }

  // Delete file if it exists (it might not exist, if user requested a local
  // file, but never wrote anything).
  if (TQUtils::fileExists(pathToDelete)){
    remove(pathToDelete.Data());

    if (!this->useTemporaryStorage)
      DEBUGclass("Deleted the file %s", pathToDelete.Data());
    else{
      DEBUGclass("Deleted the local copy of %s.", filename.Data());
    }
  }
  else{
    DEBUGclass("Nothing to delete. The file %s does not exist.", pathToDelete);
  }

  return true;
}


//////////////// Constructor and Destructor ////////////////


TQPathManager::TQPathManager(bool useTemporaryStorage){
  // Construct local output directory.
  
  //@env:[CAF_TEMP_DIR] Temporary directory CAF outputs are written to during runtime 
  //@env (ideally some fast, node-local scratch space) before copying them to their 
  //@env user-itended location at the end of execution. If not set (or resolving to an
  //@env empty string) '/tmp/<username>' will be used
  TString tempDir = TQUtils::readEnvVarValue("CAF_TEMP_DIR").c_str();
  if (tempDir.Length()==0) { 
    TString username = TQUtils::readEnvVarValue("USER").c_str();
    if (username == ""){
      // if username is not accessible, use "CAF_temporary"
      username = "CAF_temporary";
    }
    tempDir = TQUtils::readEnvVarValue("TMP");
    if (tempDir.Length()==0) {
      tempDir = "/tmp/";
    }
    tempDir = TQFolder::concatPaths(tempDir, username);
  }
  TQStringUtils::ensureTrailingText(tempDir,"/");
  this->initialize(tempDir, useTemporaryStorage);
}

TQPathManager::TQPathManager(TString localDirectory, bool useTemporaryStorage){
  this->initialize(localDirectory, useTemporaryStorage);
}

TQPathManager::~TQPathManager(){
  // 1. Loop over all pairs of local and target files. Copy all local files to
  //    their target location.
  DEBUGclass("Started Destructor");

  if (localPaths.size() > 0)
    INFOclass("Copying files from local storage to target location: %s.", this->determineTargetDir().Data());

  for (const auto& it:localPaths){
    TString targetPath = getTargetPathName(it.first);
    if (targetPath.EqualTo("")){
      WARNclass("Couldn't create target path. Not copying files.");
      break;
    }
    TString localPath = it.second;
    if (TQUtils::fileExists(localPath)){
      DEBUGclass("Copying %s to %s.", localPath.Data(), targetPath.Data());
      if (verbose) INFO("Writing file to %s.", targetPath.Data());
      if (!TQUtils::ensureDirectoryForFile(targetPath)){
        WARNclass("Cannot create the directory for the file %s. Trying to copy anyway.", targetPath.Data());
      }
      if (TQUtils::fileExists(targetPath)){
        DEBUGclass("There is already a file at %s. Copying it over.", targetPath.Data());
        remove(targetPath.Data());
      }

      // Try to just rename the file. If the target path is on another
      // volume, the rename throws 'filesystem error: cannot rename: Invalid cross-device link.' 
      // In that case, copy the file and delete it afterwards.
      try {
        std::filesystem::rename(localPath.Data(), targetPath.Data());
        DEBUGclass("File %s was be renamed to %s.", localPath.Data(), targetPath.Data());
      } catch (const std::filesystem::filesystem_error& ex) {
        DEBUGclass("File %s could not be renamed to %s. Copying instead.\nError: %s", localPath.Data(), targetPath.Data(), ex.what());
        try {
          std::filesystem::copy(localPath.Data(), targetPath.Data());
          std::filesystem::remove(localPath.Data());
          DEBUGclass("File %s was be copied to %s.", localPath.Data(), targetPath.Data());
        } catch (const std::filesystem::filesystem_error& ex) {
          ERRORclass("Could not rename or copy file %s to %s.\nError: %s", localPath.Data(), targetPath.Data(), ex.what());
        }
      }
    }
    else{
      WARNclass("You used \"TQPathManager::getLocalPath()\" to request a filename, but it seems that you did not create the file. Is this a logical error in your code? The file would have been written to %s.", targetPath.Data());
      DEBUGclass("Cannot copy %s to %s. The file does not seem to exist.", localPath.Data(), targetPath.Data());
    }
  }
  if (this == &TQPathManager::gPathManager){
    DEBUGclass("The static member path manager is being destroyed.");
    TQPathManager::gPathManagerExists = false;
  }
  else{
    DEBUGclass("A path manager that is not the static member is being destroyed.");
  }

  DEBUGclass("Completed Destructor");
}

std::vector<TString> TQPathManager::getAllTargetPaths(){
  std::vector<TString> allTargetPaths;

  allTargetPaths = this->targetPaths;

  for (const auto& it:this->localPaths){
    allTargetPaths.push_back(getTargetPathName(it.first));
  }
  return allTargetPaths;
}


///////////////////// private methods //////////////////////


TString TQPathManager::getTargetPathName(TString targetFile) const {
  if (gSystem->IsAbsoluteFileName(targetFile.Data())){
    return targetFile;
  }

  TString targetDirectory = this->determineTargetDir();
  TString targetPath = TQFolder::concatPaths(targetDirectory, targetFile);
  if (!TQUtils::ensureDirectoryForFile(targetPath)){
    ERRORclass("Cannot create directory for file %s.", targetPath.Data());
  }

  return targetPath;
}

bool TQPathManager::isInLocalPaths_target(TString filename) const {
  // Find out if filename is already in list of target files (i.e. if there is
  // a local file associated with this target file).

  // Remove leading and trailing spaces.
  filename = TQStringUtils::trim(filename);


  auto localPathname = localPaths.find(filename);
  if(localPathname == localPaths.end()){
    return false;
  }

  // If the pathname is not empty, return true.
  if (!localPathname->second.IsNull())
    return true;
  return false;
}

bool TQPathManager::isInLocalPaths_local(const TString& filePath) const {
  // Find out if filePath is already in list of local paths (i.e. if there is
  // a target file associated with this local file).

  for (const auto& it:localPaths){
    if (it.second == filePath)
      return true;
  }
  return false;
}

bool TQPathManager::isInTargetPaths(const TString& filePath) const{
  if (std::find(targetPaths.begin(), targetPaths.end(), filePath) == targetPaths.end())
    return false;
  else
    return true;
}

void TQPathManager::deleteTargetPathEntry(const TString& filePath){
  if (!isInTargetPaths(filePath)){
    DEBUGclass("Cannot delete target path entry %s, because it does not exist.", filePath.Data());
    return;
  }

  std::vector<TString>::iterator it = std::find(targetPaths.begin(), targetPaths.end(), filePath);
  targetPaths.erase(it);
  return;
}

TString TQPathManager::determineTargetDir() const {
  //@env:[CAFOUTPUTDIR] Directory which outputs produced by various CAF classes and tools should end up in
  TString targetDirectory = TQUtils::readEnvVarValue("CAFOUTPUTDIR");
  if (targetDirectory.EqualTo(""))
    return this->pwd;

  if (!gSystem->IsAbsoluteFileName(targetDirectory.Data())){
    WARNclass("The path %s specified in the environment variable \"CAFOUTPUTDIR\" is not an absolute directory. Write output in working directory instead.", targetDirectory.Data());
    return this->pwd;
  }

  if (!TQUtils::ensureDirectory(targetDirectory)){
    WARNclass("The path %s specified in the environment variable \"CAFOUTPUTDIR\" cannot be created. Write output in working directory instead.", targetDirectory.Data());
    return this->pwd;
  }

  return targetDirectory;
}

void TQPathManager::initialize(const TString& localDirectory, bool useTemporaryStorage){
  DEBUGclass("Creating instance of TQPathManager with local directory %s%s using temporary storage.", localDirectory.Data(), useTemporaryStorage ? "" : ", but not");

  this->useTemporaryStorage = useTemporaryStorage;
  this->pathsRequested = false;

  // Set current working directory and try to create output file.
  this->pwd = gSystem->pwd();
  if ((!gSystem->IsAbsoluteFileName(this->pwd.Data())) or (!TQUtils::directoryExists(this->pwd))){
    WARNclass("Current working directory could not be determined. This is not a problem if the environment variable \"CAFOUTPUTDIR\" is set.");
  }
  DEBUGclass("The current working directory is set to %s.", this->pwd.Data());
  if (!setLocalDirectory(localDirectory)){
    this->useTemporaryStorage = false;
  }
  this->verbose = false;

  if (this == &TQPathManager::gPathManager){
    DEBUG("The static member path manager is being created.");
    TQPathManager::gPathManagerExists = true;
  }
  else{
    DEBUG("A path manager that is not the static member is being created.");
  }
}
 TQPathManager.cxx:1
 TQPathManager.cxx:2
 TQPathManager.cxx:3
 TQPathManager.cxx:4
 TQPathManager.cxx:5
 TQPathManager.cxx:6
 TQPathManager.cxx:7
 TQPathManager.cxx:8
 TQPathManager.cxx:9
 TQPathManager.cxx:10
 TQPathManager.cxx:11
 TQPathManager.cxx:12
 TQPathManager.cxx:13
 TQPathManager.cxx:14
 TQPathManager.cxx:15
 TQPathManager.cxx:16
 TQPathManager.cxx:17
 TQPathManager.cxx:18
 TQPathManager.cxx:19
 TQPathManager.cxx:20
 TQPathManager.cxx:21
 TQPathManager.cxx:22
 TQPathManager.cxx:23
 TQPathManager.cxx:24
 TQPathManager.cxx:25
 TQPathManager.cxx:26
 TQPathManager.cxx:27
 TQPathManager.cxx:28
 TQPathManager.cxx:29
 TQPathManager.cxx:30
 TQPathManager.cxx:31
 TQPathManager.cxx:32
 TQPathManager.cxx:33
 TQPathManager.cxx:34
 TQPathManager.cxx:35
 TQPathManager.cxx:36
 TQPathManager.cxx:37
 TQPathManager.cxx:38
 TQPathManager.cxx:39
 TQPathManager.cxx:40
 TQPathManager.cxx:41
 TQPathManager.cxx:42
 TQPathManager.cxx:43
 TQPathManager.cxx:44
 TQPathManager.cxx:45
 TQPathManager.cxx:46
 TQPathManager.cxx:47
 TQPathManager.cxx:48
 TQPathManager.cxx:49
 TQPathManager.cxx:50
 TQPathManager.cxx:51
 TQPathManager.cxx:52
 TQPathManager.cxx:53
 TQPathManager.cxx:54
 TQPathManager.cxx:55
 TQPathManager.cxx:56
 TQPathManager.cxx:57
 TQPathManager.cxx:58
 TQPathManager.cxx:59
 TQPathManager.cxx:60
 TQPathManager.cxx:61
 TQPathManager.cxx:62
 TQPathManager.cxx:63
 TQPathManager.cxx:64
 TQPathManager.cxx:65
 TQPathManager.cxx:66
 TQPathManager.cxx:67
 TQPathManager.cxx:68
 TQPathManager.cxx:69
 TQPathManager.cxx:70
 TQPathManager.cxx:71
 TQPathManager.cxx:72
 TQPathManager.cxx:73
 TQPathManager.cxx:74
 TQPathManager.cxx:75
 TQPathManager.cxx:76
 TQPathManager.cxx:77
 TQPathManager.cxx:78
 TQPathManager.cxx:79
 TQPathManager.cxx:80
 TQPathManager.cxx:81
 TQPathManager.cxx:82
 TQPathManager.cxx:83
 TQPathManager.cxx:84
 TQPathManager.cxx:85
 TQPathManager.cxx:86
 TQPathManager.cxx:87
 TQPathManager.cxx:88
 TQPathManager.cxx:89
 TQPathManager.cxx:90
 TQPathManager.cxx:91
 TQPathManager.cxx:92
 TQPathManager.cxx:93
 TQPathManager.cxx:94
 TQPathManager.cxx:95
 TQPathManager.cxx:96
 TQPathManager.cxx:97
 TQPathManager.cxx:98
 TQPathManager.cxx:99
 TQPathManager.cxx:100
 TQPathManager.cxx:101
 TQPathManager.cxx:102
 TQPathManager.cxx:103
 TQPathManager.cxx:104
 TQPathManager.cxx:105
 TQPathManager.cxx:106
 TQPathManager.cxx:107
 TQPathManager.cxx:108
 TQPathManager.cxx:109
 TQPathManager.cxx:110
 TQPathManager.cxx:111
 TQPathManager.cxx:112
 TQPathManager.cxx:113
 TQPathManager.cxx:114
 TQPathManager.cxx:115
 TQPathManager.cxx:116
 TQPathManager.cxx:117
 TQPathManager.cxx:118
 TQPathManager.cxx:119
 TQPathManager.cxx:120
 TQPathManager.cxx:121
 TQPathManager.cxx:122
 TQPathManager.cxx:123
 TQPathManager.cxx:124
 TQPathManager.cxx:125
 TQPathManager.cxx:126
 TQPathManager.cxx:127
 TQPathManager.cxx:128
 TQPathManager.cxx:129
 TQPathManager.cxx:130
 TQPathManager.cxx:131
 TQPathManager.cxx:132
 TQPathManager.cxx:133
 TQPathManager.cxx:134
 TQPathManager.cxx:135
 TQPathManager.cxx:136
 TQPathManager.cxx:137
 TQPathManager.cxx:138
 TQPathManager.cxx:139
 TQPathManager.cxx:140
 TQPathManager.cxx:141
 TQPathManager.cxx:142
 TQPathManager.cxx:143
 TQPathManager.cxx:144
 TQPathManager.cxx:145
 TQPathManager.cxx:146
 TQPathManager.cxx:147
 TQPathManager.cxx:148
 TQPathManager.cxx:149
 TQPathManager.cxx:150
 TQPathManager.cxx:151
 TQPathManager.cxx:152
 TQPathManager.cxx:153
 TQPathManager.cxx:154
 TQPathManager.cxx:155
 TQPathManager.cxx:156
 TQPathManager.cxx:157
 TQPathManager.cxx:158
 TQPathManager.cxx:159
 TQPathManager.cxx:160
 TQPathManager.cxx:161
 TQPathManager.cxx:162
 TQPathManager.cxx:163
 TQPathManager.cxx:164
 TQPathManager.cxx:165
 TQPathManager.cxx:166
 TQPathManager.cxx:167
 TQPathManager.cxx:168
 TQPathManager.cxx:169
 TQPathManager.cxx:170
 TQPathManager.cxx:171
 TQPathManager.cxx:172
 TQPathManager.cxx:173
 TQPathManager.cxx:174
 TQPathManager.cxx:175
 TQPathManager.cxx:176
 TQPathManager.cxx:177
 TQPathManager.cxx:178
 TQPathManager.cxx:179
 TQPathManager.cxx:180
 TQPathManager.cxx:181
 TQPathManager.cxx:182
 TQPathManager.cxx:183
 TQPathManager.cxx:184
 TQPathManager.cxx:185
 TQPathManager.cxx:186
 TQPathManager.cxx:187
 TQPathManager.cxx:188
 TQPathManager.cxx:189
 TQPathManager.cxx:190
 TQPathManager.cxx:191
 TQPathManager.cxx:192
 TQPathManager.cxx:193
 TQPathManager.cxx:194
 TQPathManager.cxx:195
 TQPathManager.cxx:196
 TQPathManager.cxx:197
 TQPathManager.cxx:198
 TQPathManager.cxx:199
 TQPathManager.cxx:200
 TQPathManager.cxx:201
 TQPathManager.cxx:202
 TQPathManager.cxx:203
 TQPathManager.cxx:204
 TQPathManager.cxx:205
 TQPathManager.cxx:206
 TQPathManager.cxx:207
 TQPathManager.cxx:208
 TQPathManager.cxx:209
 TQPathManager.cxx:210
 TQPathManager.cxx:211
 TQPathManager.cxx:212
 TQPathManager.cxx:213
 TQPathManager.cxx:214
 TQPathManager.cxx:215
 TQPathManager.cxx:216
 TQPathManager.cxx:217
 TQPathManager.cxx:218
 TQPathManager.cxx:219
 TQPathManager.cxx:220
 TQPathManager.cxx:221
 TQPathManager.cxx:222
 TQPathManager.cxx:223
 TQPathManager.cxx:224
 TQPathManager.cxx:225
 TQPathManager.cxx:226
 TQPathManager.cxx:227
 TQPathManager.cxx:228
 TQPathManager.cxx:229
 TQPathManager.cxx:230
 TQPathManager.cxx:231
 TQPathManager.cxx:232
 TQPathManager.cxx:233
 TQPathManager.cxx:234
 TQPathManager.cxx:235
 TQPathManager.cxx:236
 TQPathManager.cxx:237
 TQPathManager.cxx:238
 TQPathManager.cxx:239
 TQPathManager.cxx:240
 TQPathManager.cxx:241
 TQPathManager.cxx:242
 TQPathManager.cxx:243
 TQPathManager.cxx:244
 TQPathManager.cxx:245
 TQPathManager.cxx:246
 TQPathManager.cxx:247
 TQPathManager.cxx:248
 TQPathManager.cxx:249
 TQPathManager.cxx:250
 TQPathManager.cxx:251
 TQPathManager.cxx:252
 TQPathManager.cxx:253
 TQPathManager.cxx:254
 TQPathManager.cxx:255
 TQPathManager.cxx:256
 TQPathManager.cxx:257
 TQPathManager.cxx:258
 TQPathManager.cxx:259
 TQPathManager.cxx:260
 TQPathManager.cxx:261
 TQPathManager.cxx:262
 TQPathManager.cxx:263
 TQPathManager.cxx:264
 TQPathManager.cxx:265
 TQPathManager.cxx:266
 TQPathManager.cxx:267
 TQPathManager.cxx:268
 TQPathManager.cxx:269
 TQPathManager.cxx:270
 TQPathManager.cxx:271
 TQPathManager.cxx:272
 TQPathManager.cxx:273
 TQPathManager.cxx:274
 TQPathManager.cxx:275
 TQPathManager.cxx:276
 TQPathManager.cxx:277
 TQPathManager.cxx:278
 TQPathManager.cxx:279
 TQPathManager.cxx:280
 TQPathManager.cxx:281
 TQPathManager.cxx:282
 TQPathManager.cxx:283
 TQPathManager.cxx:284
 TQPathManager.cxx:285
 TQPathManager.cxx:286
 TQPathManager.cxx:287
 TQPathManager.cxx:288
 TQPathManager.cxx:289
 TQPathManager.cxx:290
 TQPathManager.cxx:291
 TQPathManager.cxx:292
 TQPathManager.cxx:293
 TQPathManager.cxx:294
 TQPathManager.cxx:295
 TQPathManager.cxx:296
 TQPathManager.cxx:297
 TQPathManager.cxx:298
 TQPathManager.cxx:299
 TQPathManager.cxx:300
 TQPathManager.cxx:301
 TQPathManager.cxx:302
 TQPathManager.cxx:303
 TQPathManager.cxx:304
 TQPathManager.cxx:305
 TQPathManager.cxx:306
 TQPathManager.cxx:307
 TQPathManager.cxx:308
 TQPathManager.cxx:309
 TQPathManager.cxx:310
 TQPathManager.cxx:311
 TQPathManager.cxx:312
 TQPathManager.cxx:313
 TQPathManager.cxx:314
 TQPathManager.cxx:315
 TQPathManager.cxx:316
 TQPathManager.cxx:317
 TQPathManager.cxx:318
 TQPathManager.cxx:319
 TQPathManager.cxx:320
 TQPathManager.cxx:321
 TQPathManager.cxx:322
 TQPathManager.cxx:323
 TQPathManager.cxx:324
 TQPathManager.cxx:325
 TQPathManager.cxx:326
 TQPathManager.cxx:327
 TQPathManager.cxx:328
 TQPathManager.cxx:329
 TQPathManager.cxx:330
 TQPathManager.cxx:331
 TQPathManager.cxx:332
 TQPathManager.cxx:333
 TQPathManager.cxx:334
 TQPathManager.cxx:335
 TQPathManager.cxx:336
 TQPathManager.cxx:337
 TQPathManager.cxx:338
 TQPathManager.cxx:339
 TQPathManager.cxx:340
 TQPathManager.cxx:341
 TQPathManager.cxx:342
 TQPathManager.cxx:343
 TQPathManager.cxx:344
 TQPathManager.cxx:345
 TQPathManager.cxx:346
 TQPathManager.cxx:347
 TQPathManager.cxx:348
 TQPathManager.cxx:349
 TQPathManager.cxx:350
 TQPathManager.cxx:351
 TQPathManager.cxx:352
 TQPathManager.cxx:353
 TQPathManager.cxx:354
 TQPathManager.cxx:355
 TQPathManager.cxx:356
 TQPathManager.cxx:357
 TQPathManager.cxx:358
 TQPathManager.cxx:359
 TQPathManager.cxx:360
 TQPathManager.cxx:361
 TQPathManager.cxx:362
 TQPathManager.cxx:363
 TQPathManager.cxx:364
 TQPathManager.cxx:365
 TQPathManager.cxx:366
 TQPathManager.cxx:367
 TQPathManager.cxx:368
 TQPathManager.cxx:369
 TQPathManager.cxx:370
 TQPathManager.cxx:371
 TQPathManager.cxx:372
 TQPathManager.cxx:373
 TQPathManager.cxx:374
 TQPathManager.cxx:375
 TQPathManager.cxx:376
 TQPathManager.cxx:377
 TQPathManager.cxx:378
 TQPathManager.cxx:379
 TQPathManager.cxx:380
 TQPathManager.cxx:381
 TQPathManager.cxx:382
 TQPathManager.cxx:383
 TQPathManager.cxx:384
 TQPathManager.cxx:385
 TQPathManager.cxx:386
 TQPathManager.cxx:387
 TQPathManager.cxx:388
 TQPathManager.cxx:389
 TQPathManager.cxx:390
 TQPathManager.cxx:391
 TQPathManager.cxx:392
 TQPathManager.cxx:393
 TQPathManager.cxx:394
 TQPathManager.cxx:395
 TQPathManager.cxx:396
 TQPathManager.cxx:397
 TQPathManager.cxx:398
 TQPathManager.cxx:399
 TQPathManager.cxx:400
 TQPathManager.cxx:401
 TQPathManager.cxx:402
 TQPathManager.cxx:403
 TQPathManager.cxx:404
 TQPathManager.cxx:405
 TQPathManager.cxx:406
 TQPathManager.cxx:407
 TQPathManager.cxx:408
 TQPathManager.cxx:409
 TQPathManager.cxx:410
 TQPathManager.cxx:411
 TQPathManager.cxx:412
 TQPathManager.cxx:413
 TQPathManager.cxx:414
 TQPathManager.cxx:415
 TQPathManager.cxx:416
 TQPathManager.cxx:417
 TQPathManager.cxx:418
 TQPathManager.cxx:419
 TQPathManager.cxx:420
 TQPathManager.cxx:421
 TQPathManager.cxx:422
 TQPathManager.cxx:423
 TQPathManager.cxx:424
 TQPathManager.cxx:425
 TQPathManager.cxx:426
 TQPathManager.cxx:427
 TQPathManager.cxx:428
 TQPathManager.cxx:429
 TQPathManager.cxx:430
 TQPathManager.cxx:431
 TQPathManager.cxx:432
 TQPathManager.cxx:433
 TQPathManager.cxx:434
 TQPathManager.cxx:435
 TQPathManager.cxx:436
 TQPathManager.cxx:437
 TQPathManager.cxx:438
 TQPathManager.cxx:439
 TQPathManager.cxx:440
 TQPathManager.cxx:441
 TQPathManager.cxx:442
 TQPathManager.cxx:443
 TQPathManager.cxx:444
 TQPathManager.cxx:445
 TQPathManager.cxx:446
 TQPathManager.cxx:447
 TQPathManager.cxx:448
 TQPathManager.cxx:449
 TQPathManager.cxx:450
 TQPathManager.cxx:451
 TQPathManager.cxx:452
 TQPathManager.cxx:453
 TQPathManager.cxx:454
 TQPathManager.cxx:455
 TQPathManager.cxx:456
 TQPathManager.cxx:457
 TQPathManager.cxx:458
 TQPathManager.cxx:459
 TQPathManager.cxx:460
 TQPathManager.cxx:461
 TQPathManager.cxx:462
 TQPathManager.cxx:463
 TQPathManager.cxx:464
 TQPathManager.cxx:465
 TQPathManager.cxx:466
 TQPathManager.cxx:467
 TQPathManager.cxx:468
 TQPathManager.cxx:469
 TQPathManager.cxx:470
 TQPathManager.cxx:471
 TQPathManager.cxx:472
 TQPathManager.cxx:473
 TQPathManager.cxx:474
 TQPathManager.cxx:475
 TQPathManager.cxx:476
 TQPathManager.cxx:477
 TQPathManager.cxx:478
 TQPathManager.cxx:479
 TQPathManager.cxx:480
 TQPathManager.cxx:481
 TQPathManager.cxx:482
 TQPathManager.cxx:483
 TQPathManager.cxx:484
 TQPathManager.cxx:485
 TQPathManager.cxx:486
 TQPathManager.cxx:487
 TQPathManager.cxx:488
 TQPathManager.cxx:489
 TQPathManager.cxx:490
 TQPathManager.cxx:491
 TQPathManager.cxx:492
 TQPathManager.cxx:493
 TQPathManager.cxx:494
 TQPathManager.cxx:495
 TQPathManager.cxx:496
 TQPathManager.cxx:497
 TQPathManager.cxx:498
 TQPathManager.cxx:499
 TQPathManager.cxx:500
 TQPathManager.cxx:501
 TQPathManager.cxx:502
 TQPathManager.cxx:503
 TQPathManager.cxx:504
 TQPathManager.cxx:505
 TQPathManager.cxx:506
 TQPathManager.cxx:507
 TQPathManager.cxx:508
 TQPathManager.cxx:509
 TQPathManager.cxx:510
 TQPathManager.cxx:511
 TQPathManager.cxx:512
 TQPathManager.cxx:513
 TQPathManager.cxx:514
 TQPathManager.cxx:515
 TQPathManager.cxx:516
 TQPathManager.cxx:517
 TQPathManager.cxx:518
 TQPathManager.cxx:519
 TQPathManager.cxx:520
 TQPathManager.cxx:521
 TQPathManager.cxx:522
 TQPathManager.cxx:523
 TQPathManager.cxx:524
 TQPathManager.cxx:525
 TQPathManager.cxx:526
 TQPathManager.cxx:527
 TQPathManager.cxx:528
 TQPathManager.cxx:529
 TQPathManager.cxx:530
 TQPathManager.cxx:531
 TQPathManager.cxx:532
 TQPathManager.cxx:533
 TQPathManager.cxx:534
 TQPathManager.cxx:535
 TQPathManager.cxx:536
 TQPathManager.cxx:537
 TQPathManager.cxx:538
 TQPathManager.cxx:539
 TQPathManager.cxx:540
 TQPathManager.cxx:541
 TQPathManager.cxx:542
 TQPathManager.cxx:543
 TQPathManager.cxx:544
 TQPathManager.cxx:545
 TQPathManager.cxx:546
 TQPathManager.cxx:547
 TQPathManager.cxx:548
 TQPathManager.cxx:549
 TQPathManager.cxx:550
 TQPathManager.cxx:551
 TQPathManager.cxx:552
 TQPathManager.cxx:553
 TQPathManager.cxx:554
 TQPathManager.cxx:555
 TQPathManager.cxx:556
 TQPathManager.cxx:557
 TQPathManager.cxx:558
 TQPathManager.cxx:559
 TQPathManager.cxx:560
 TQPathManager.cxx:561
 TQPathManager.cxx:562
 TQPathManager.cxx:563
 TQPathManager.cxx:564
 TQPathManager.cxx:565
 TQPathManager.cxx:566
 TQPathManager.cxx:567
 TQPathManager.cxx:568
 TQPathManager.cxx:569
 TQPathManager.cxx:570
 TQPathManager.cxx:571
 TQPathManager.cxx:572
 TQPathManager.cxx:573
 TQPathManager.cxx:574
 TQPathManager.cxx:575
 TQPathManager.cxx:576
 TQPathManager.cxx:577
 TQPathManager.cxx:578
 TQPathManager.cxx:579
 TQPathManager.cxx:580
 TQPathManager.cxx:581
 TQPathManager.cxx:582
 TQPathManager.cxx:583
 TQPathManager.cxx:584
 TQPathManager.cxx:585
 TQPathManager.cxx:586
 TQPathManager.cxx:587
 TQPathManager.cxx:588
 TQPathManager.cxx:589
 TQPathManager.cxx:590
 TQPathManager.cxx:591
 TQPathManager.cxx:592
 TQPathManager.cxx:593
 TQPathManager.cxx:594
 TQPathManager.cxx:595
 TQPathManager.cxx:596
 TQPathManager.cxx:597
 TQPathManager.cxx:598
 TQPathManager.cxx:599
 TQPathManager.cxx:600
 TQPathManager.cxx:601
 TQPathManager.cxx:602
 TQPathManager.cxx:603
 TQPathManager.cxx:604
 TQPathManager.cxx:605