/*
 *
 * Copyright (c) 2003 Dr John Maddock
 * Use, modification and distribution is subject to the 
 * Boost Software License, Version 1.0. (See accompanying file 
 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 *
 * This file implements the bcp_implementation virtuals.
 */

#include "bcp_imp.hpp"
#include "licence_info.hpp"
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/fstream.hpp>
#include <iostream>
#include <stdexcept>
#include <boost/regex.hpp>
#include <string>

bcp_implementation::bcp_implementation()
  : m_list_mode(false), m_list_summary_mode(false), m_license_mode(false), m_cvs_mode(false), 
  m_svn_mode(false), m_unix_lines(false), m_scan_mode(false), m_bsl_convert_mode(false), 
  m_bsl_summary_mode(false), m_namespace_alias(false), m_list_namespaces(false)
{
}

bcp_implementation::~bcp_implementation()
{
}

bcp_application::~bcp_application()
{
}

void bcp_implementation::enable_list_mode()
{
   m_list_mode = true;
}

void bcp_implementation::enable_summary_list_mode()
{
   m_list_mode = true;
   m_list_summary_mode = true;
}

void bcp_implementation::enable_cvs_mode()
{
   m_cvs_mode = true;
}

void bcp_implementation::enable_svn_mode()
{
   m_svn_mode = true;
}

void bcp_implementation::enable_scan_mode()
{
   m_scan_mode = true;
}

void bcp_implementation::enable_license_mode()
{
   m_license_mode = true;
}

void bcp_implementation::enable_bsl_convert_mode()
{
   m_bsl_convert_mode = true;
}

void bcp_implementation::enable_bsl_summary_mode()
{
   m_bsl_summary_mode = true;
}

void bcp_implementation::enable_unix_lines()
{
   m_unix_lines = true;
}

void bcp_implementation::set_boost_path(const char* p)
{
   // Hack to strip trailing slashes from the path 
   m_boost_path = (fs::path(p, fs::native) / "boost").parent_path(); 
   fs::path check = m_boost_path / "boost" / "version.hpp";
   if(!fs::exists(check))
   {
      std::string s = "The Boost path appears to have been incorrectly set: could not find boost/version.hpp in ";
      s += m_boost_path.string();
      std::runtime_error e(s);
      throw e;
   }
}

void bcp_implementation::set_destination(const char* p)
{
   m_dest_path = fs::path(p, fs::native);
}

void bcp_implementation::add_module(const char* p)
{
   m_module_list.push_back(p);
}

void bcp_implementation::set_namespace(const char* name)
{
   m_namespace_name = name;
}

void bcp_implementation::set_namespace_alias(bool b)
{
   m_namespace_alias = b;
}

void bcp_implementation::set_namespace_list(bool b)
{
   m_list_namespaces = b;
   m_list_mode = b;
}

fs::path get_short_path(const fs::path& p)
{
   // truncate path no more than "x/y":
   std::string s = p.string();
   std::string::size_type n = s.find('/');
   if(n != std::string::npos)
   {
      n = s.find('/', n+1);
      if(n != std::string::npos)
         s.erase(n);
   }
   return s;
}

int bcp_implementation::run()
{
   //
   // check output path is OK:
   //
   if(!m_list_mode && !m_license_mode && !fs::exists(m_dest_path))
   {
      std::string msg("Destination path does not exist: ");
      msg.append(m_dest_path.native_file_string());
      std::runtime_error e(msg);
      boost::throw_exception(e);
   }
   //
   // Check Boost path is OK if it hasn't been checked already:
   //
   if(m_boost_path == "")
   {
      set_boost_path("");
   }
   // start by building a list of permitted files
   // if m_cvs_mode is true:
   if(m_cvs_mode)
   {
      std::cerr << "CAUTION: Boost is no longer in CVS, cvs mode may not work anymore!!!" << std::endl;
      scan_cvs_path(fs::path());
   }
   if(m_svn_mode)
   {
      scan_svn_path(fs::path());
   }
   //
   // if in license mode, try to load more/blanket_permission.txt
   //
   fs::path blanket_permission(m_boost_path / "more" / "blanket-permission.txt");
   if (fs::exists(blanket_permission)) {
     fs::ifstream in(blanket_permission);
     std::string line;
     while (std::getline(in, line)) {
       static const boost::regex e("([^(]+)\\(");
       boost::smatch result;
       if (boost::regex_search(line, result, e))
         m_bsl_authors.insert(format_authors_name(result[1]));
     }
   }

   //
   // scan through modules looking for the equivalent
   // file to add to our list:
   //
   std::list<std::string>::const_iterator i = m_module_list.begin();
   std::list<std::string>::const_iterator j = m_module_list.end();
   while(i != j)
   {
      //
      // convert *i to a path - could be native or portable:
      //
      fs::path module;
      fs::path exmodule;
      try{
         module = fs::path(*i);
         exmodule = fs::path(*i + ".hpp");
      }
      catch(...)
      {
         module = fs::path(*i, fs::native);
         exmodule = fs::path(*i + ".hpp", fs::native);
      }
      
      if(m_scan_mode)
      {
         // in scan mode each module must be a real file:
         add_file_dependencies(module, true);
      }
      else
      {
         int count = 0;
         if(fs::exists(m_boost_path / "tools" / module))
         {
            add_path(fs::path("tools") / module);
            ++count;
         }
         if(fs::exists(m_boost_path / "libs" / module))
         {
            add_path(fs::path("libs") / module);
            ++count;
         }
         if(fs::exists(m_boost_path / "boost" / module))
         {
            add_path(fs::path("boost") / module);
            ++count;
         }
         if(fs::exists(m_boost_path / "boost" / exmodule))
         {
            add_path(fs::path("boost") / exmodule);
            ++count;
         }
         if(fs::exists(m_boost_path / module))
         {
            add_path(module);
            ++count;
         }
      }
      ++i;
   }
   //
   // now perform output:
   //
   if(m_list_namespaces)
   {
      // List the namespaces, in two lists, headers and source files
      // first, then everything else afterwards:
      //
      boost::regex important_file("boost/.*|libs/[^/]*/(?:[^/]*/)?/src/.*");
      std::map<std::string, fs::path>::const_iterator i, j;
      i = m_top_namespaces.begin();
      j = m_top_namespaces.end();
      std::cout << "\n\nThe top level namespaces found for header and source files were:\n";
      while(i != j)
      {
         if(regex_match(i->second.string(), important_file))
            std::cout << i->first << " (from " << i->second << ")" << std::endl;
         ++i;
      }

      i = m_top_namespaces.begin();
      std::cout << "\n\nThe top level namespaces found for all other source files were:\n";
      while(i != j)
      {
         if(!regex_match(i->second.string(), important_file))
            std::cout << i->first << " (from " << i->second << ")" << std::endl;
         ++i;
      }
      return 0;
   }
   std::set<fs::path, path_less>::iterator m, n;
   std::set<fs::path, path_less> short_paths;
   m = m_copy_paths.begin();
   n = m_copy_paths.end();
   if(!m_license_mode)
   {
      while(m != n)
      {
         if(m_list_summary_mode)
         {
            fs::path p = get_short_path(*m);
            if(short_paths.find(p) == short_paths.end())
            {
               short_paths.insert(p);
               std::cout << p.string() << "\n";
            }
         }
         else if(m_list_mode)
            std::cout << m->string() << "\n";
         else
            copy_path(*m);
         ++m;
      }
   }
   else
      output_license_info();
   return 0;
}

pbcp_application bcp_application::create()
{
   pbcp_application result(static_cast<bcp_application*>(new bcp_implementation()));
   return result;
}
