//-----------------------------------------------------------
// Copyright Christian Arnault LAL-Orsay CNRS
// arnault@lal.in2p3.fr
// See the complete license in cmt_license.txt "http://www.cecill.info". 
//-----------------------------------------------------------

#include "cmt_system.h"
#include "cmt.h"
#include "cmt_install_area.h"
#include "cmt_syntax.h"
#include "cmt_use.h"
#include "cmt_symbol.h"
#include "cmt_cmtpath_pattern.h"
#include "cmt_project.h"

CmtInstallAreaMgr& CmtInstallAreaMgr::instance ()
{
  static CmtInstallAreaMgr me;

  return (me);
}

void CmtInstallAreaMgr::setup_current_installarea ()
{
  m_installarea = build_current_installarea ();

  if (m_installarea == "") return;

  cmt_string macro_name;

  Project* project = Project::find_by_cmtpath (m_installarea);

  if (project != 0)
    {
      macro_name = project->get_name ();
    }
  else
    {
      macro_name = "cmt";
    }

  macro_name += "_installarea_prefix";

  Symbol* macro = Symbol::find (macro_name);

  cmt_string installarea_prefix;

  if (macro != 0)
    {
      installarea_prefix = macro->build_macro_value ();
    }

  if (installarea_prefix != "")
    {
      m_installarea += CmtSystem::file_separator ();
      m_installarea += installarea_prefix;
    }

  Use& current_use = Use::current ();
  cmt_string buffer;

  if (!Symbol::is_selected ("CMTINSTALLAREA"))
    {
      buffer = "macro CMTINSTALLAREA \"";
      buffer += m_installarea;
      buffer += "\"";
      
      SyntaxParser::parse_requirements_line (buffer, &current_use);
      buffer = "";
    }
}

void CmtInstallAreaMgr::setup ()
{
  m_installarea = build_current_installarea ();

  setup_current_installarea ();
}

void CmtInstallAreaMgr::config () const
{
  cmt_string installarea = build_current_installarea ();

  CmtPathPattern::apply_all ();

  if (installarea == "") return;

  if (!Cmt::get_quiet ())
    {
      cerr << "#CMT> Warning: Doing cleanup in the installation area " << installarea << endl;
    }

  Symbol* macro = Symbol::find ("cmt_installarea_paths");
  if (macro == 0) return;
  cmt_string installarea_paths = macro->build_macro_value ();

  CmtSystem::cmt_string_vector areapaths;
  CmtSystem::split (installarea_paths, " \t", areapaths);

  // Try a cleanup only in this selected install area

  for (int i = 0; i < areapaths.size (); i++)
    {
      const cmt_string& p = areapaths[i];
      
      cmt_string path = installarea;
      path += CmtSystem::file_separator ();
      path += p;
      
      Symbol::expand (path);

      path.replace_all ("/", CmtSystem::file_separator ());
      path.replace_all ("\\", CmtSystem::file_separator ());
      
      CmtSystem::cmt_string_vector refs;
      cmt_regexp expression (".*[.]cmtref$");

      // Look for all cmtref files in this PATH pattern

      CmtSystem::scan_dir (path, expression, refs);
      
      for (int j = 0; j < refs.size (); j++)
        {
          const cmt_string& ref_file = refs[j];

	  // We get the absolute location of the installed file

          cmt_string ref;
          ref.read (ref_file);
          int pos;

	  ref.replace_all ("\"", "");

	  if (Cmt::get_debug ())
	    {
	      cout << "CmtInstallAreaMgr::config> " << ref_file << " " << ref << endl;
	    }

	  pos = ref.find ("\r\n");
          if (pos != cmt_string::npos) ref.erase (pos);
	  pos = ref.find ('\n');
          if (pos != cmt_string::npos) ref.erase (pos);
	  pos = ref.find ('\r');
          if (pos != cmt_string::npos) ref.erase (pos);
	  pos = ref.find (' ');
          if (pos != cmt_string::npos) ref.erase (pos);

	  //  If the referenced file cannot be reached we remove the 
	  // corresponding installation
	  //  (this happens if the referenced file has be removed, or 
	  //   moved away)
          
          if (!CmtSystem::test_file (ref))
            {
              cmt_string ref_name;

	      // Get the name of the referenced file
              CmtSystem::basename (ref, ref_name);

	      // Get the installation directory
              CmtSystem::dirname (ref_file, ref);

              ref += CmtSystem::file_separator ();
              ref += ref_name;
              
	      // Remove both the installed file
	      // and the reference file

	      if (!Cmt::get_quiet ())
		{
		  cerr << "# Removing obsolete installed file ["  << ref << "]";
		  cerr << "  (and " << ref_file << ")" << endl;
		}

              CmtSystem::remove_file (ref);
              CmtSystem::remove_file (ref_file);
            }
        }
    }
}

const cmt_string& CmtInstallAreaMgr::get_installarea () const
{
  return (m_installarea);
}

cmt_string CmtInstallAreaMgr::build_current_installarea () const
{
  cmt_string installarea;

  const cmt_string pwd = CmtSystem::pwd ();

  installarea = Project::find_in_cmt_paths (pwd);

  return (installarea);
}



