/* -*- c++ -*- */
#ifndef GENERATOR_H__
#define GENERATOR_H__

#include <akaxiso/akaxiso.h>
#include "classdefs.h"
#include "processor.h"

class generator {
  registry *registry_;
  typedef std::vector<const class_def*> const_class_defs;

  std::ostream &logstm_;
  std::string dirpath_;
  std::ofstream el_;
  std::ofstream xiso_;
  std::ofstream ximpl_;
  
  qname_set xisodecl_generated_;
  
  bool soft_resolve(qname_set &resolving, const aka::qname &name, 
		    const_class_defs &dependency, qname_set &forwarded);
  bool hard_resolve(qname_set &resvolving, const aka::qname &name, 
		    const_class_defs &dependency, qname_set &processing);
  
  bool generate_type(qname_set &resolved, const aka::qname &to_resolve, 
		     qname_set &toplevels);
  void generate_one_ns(qname_set &resolved, aka::id_type ns_id, 
		       qname_set &simpleTypes, qname_set &topLevels);
  void generate_instantiate_xiso(const aka::id_type ns_id);
  void generate_serialize_methods(const aka::id_type ns_id);

  void generate_sequence(const class_def &def, const qname_set &resolved);
  void generate_choice(const class_def &def, const qname_set &resolved);
  void generate_all(const class_def &def, const qname_set &resolved);
  void generate_array(const class_def &def, const qname_set &resolved);
  void generate_simplecontent(const class_def &def);
  void generate_simpletype(const class_def &def);

  void write_ptrmember_decl(const element_types &etypes, const qname_set &resolved); 

  void write_leaf_decl(const class_def &def, const std::string &leaftmp);
  void write_member_decls(const element_types &etypes);
  void write_attribute_decls(const attribute_defs &attrs);
  void write_member_leaves(const aka::qname &name, const element_types &etypes);
  void write_item_leaves(const aka::qname &name, const element_types &etypes);
  void write_attribute_leaves(const aka::qname &name, const attribute_defs &attrs);
  void write_header(std::ostream &ostm, const std::string &basename);
  void write_footer(std::ostream &ostm, const std::string &basename);

  static std::string escape_filename(const std::string &fn);
  std::string cppname(const aka::qname &name) const;
  std::string declname(const aka::qname &name) const;
  std::string leafdecl(const aka::qname &name) const;
  std::string leafname(const aka::qname &name) const;
  std::string membername(const aka::qname &name) const;
  void begin_model_method(const aka::qname &name);
  void end_model_method();

public:
  generator(std::ostream &ostm, const std::string &dirpath) 
    : registry_(0), logstm_(ostm), dirpath_(dirpath) {}
  void generate(registry &reg);
};

#endif
