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

#include <akaxiso/classes/qname.h>
#include <akaxiso/classes/occurrence.h>
#include <akaxiso/classes/element_ptr.h>
#include <map>

namespace aka2 {

  struct element_op;
  struct itemtype {
    itemtype(element_op *op = 0, int minOccurs = 1, int maxOccurs = 1) 
      : op_(op), occurrence_(minOccurs, maxOccurs){}

    bool equals(const void *lhs, const void *rhs) const;

    void set_occurrence(const occurrence &occ) {
      occurrence_ = occ;
    }
    const occurrence &get_occurrence() const {
      return occurrence_;
    } 
    const element_op &get_op() const {
      return *op_;
    }

    schematype_id get_schematype() const;
    
  private:
    element_op *op_;
    occurrence occurrence_;
  };

  typedef std::map<qname, itemtype, qname_less> itemtypes;

  class item {
  public:
    item() {}
    item(const qname &name, void *element, const element_op &op)
      : name_(name), element_(element, op){  }
    item(const item &i) : 
      name_(i.name_), element_(i.element_) {
    }
    ~item(){}

    const item& operator=(const item& rhs);

    const element_op &get_op() const { return element_.get_op(); }
    void *element() { return element_.get_ptr(); }
    const void *element() const { return element_.get_ptr(); }
    const qname &get_name() const { return name_; }
    bool is_element() const { return name_.local()[0] != '&'; }
  protected:
    void assign(const item &rhs);

    qname name_;
    element_ptr element_;
  };


  bool item_of(const aka2::item &i, const std::string &tagname);
  
  template<class T>
  T& item_cast(aka2::item &i) {
    return *static_cast<T*>(i.element());
  } 
  
  template<class T>
  const T& item_cast(const aka2::item &i) {
    return *static_cast<const T*>(i.element());
  } 

}




#endif
