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

#ifndef __cmt_project_h__
#define __cmt_project_h__

#include "cmt_parser.h"
#include "cmt_system.h"
#include "cmt_awk.h"

class Project;

class ProjectFactory : public IProjectFactory
{
public:
  static IProjectFactory& instance ();

public:
  void reset ();
  Project* create_project (const cmt_string& path,
			   const cmt_string& path_source,
			   Project* parent);

private:
  Project* m_first;
  Project* m_previous;
  int m_id;
};

class IProjectAction
{
public:
  virtual bool run (const Project& project) = 0;
};

class IProjectVisitor
{
public:
  virtual void pre (Project* p) = 0;
  virtual void in (Project* p) = 0;
  virtual void post (Project* p) = 0;
};

class Project
{
public:

  typedef cmt_vector<Project> ProjectVector;
  typedef cmt_vector<Project*> ProjectPtrVector;

  static void create (const cmt_string& name);

  static Project* find_by_name (const cmt_string& name);
  static Project* find_by_cmtpath (const cmt_string& cmtpath);
  static Project* get_current ();
  static Project* add (const cmt_string& name,
		       const cmt_string& release);

  static ProjectVector& projects ();
  static void clear_all ();
  static void show_all ();
  static void show_paths ();
  static const cmt_string& get_project_file_name ();

  static void fill_selection (int depth, CmtSystem::cmt_string_vector& path_selections);

  static void broadcast (IProjectAction& action);
  static void reverse_broadcast (IProjectAction& action);
  static void scan_paths (PathScanner& scanner, PathScanner::actor& actor);
  static void scan_paths_for_package (PathScanner& scanner, const cmt_string& name);

  static cmt_string find_in_cmt_paths (const cmt_string& path);

  static void fill_cmtpaths (cmt_string& buffer);

  static void start_visit (IProjectVisitor& visitor);

public:

  Project ();

  const cmt_string& get_name () const;
  const cmt_string& get_release () const;
  const cmt_string& get_cmtpath () const;
  const cmt_string& get_cmtpath_pwd () const;
  const cmt_string& get_cmtpath_source () const;
  int get_children_size () const;
  Project* get_child (int index) const;
  bool visited () const;

  void set_name (const cmt_string& name);
  void set_release (const cmt_string& release);
  void set_cmtpath (const cmt_string& path);
  void set_cmtpath_pwd (const cmt_string& path);
  void set_cmtpath_source (const cmt_string& source);
  void clear ();
  void configure ();
  void add_parent (Project* p);
  void add_child (Project* p);

  void use_action (const cmt_string& name, const cmt_string& release);

  Project& operator = (const Project& other);
  bool operator == (const cmt_string& name) const;
  bool operator != (const cmt_string& name) const;

  void show ();
  void show_strategies () const;
  int get_build_strategy () const;
  int get_setup_strategy () const;
  void set_build_strategy (int mask, int strategy);
  void set_setup_strategy (int mask, int strategy);

  void visit (IProjectVisitor& visitor);

private:

  void fill_cmtpath (cmt_string& buffer);

  cmt_string m_name;
  cmt_string m_release;

  ProjectPtrVector m_parents;
  ProjectPtrVector m_children;

  bool m_visited;

  cmt_string m_cmtpath;
  cmt_string m_cmtpath_pwd;
  cmt_string m_cmtpath_source;

  int m_build_strategy_mask;
  int m_build_strategy;
  int m_setup_strategy_mask;
  int m_setup_strategy;

  bool m_configured;

  Tag* m_prototypes_tag;
  Tag* m_no_prototypes_tag;
  Tag* m_with_installarea_tag;
  Tag* m_without_installarea_tag;

  Tag* m_setup_config_tag;
  Tag* m_setup_no_config_tag;
  Tag* m_setup_root_tag;
  Tag* m_setup_no_root_tag;
  Tag* m_setup_cleanup_tag;
  Tag* m_setup_no_cleanup_tag;

};


#endif
