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

#include <akaxiso/classes/traits.h>
#include <akaxiso/classes/simpletype.h>
#include <akaxiso/classes/global_attributes.h>
#include <akaxiso/classes/attribute.h>
#include <akaxiso/classes/construct.h>
#include <akaxiso/classes/destruct.h>

namespace aka2 {

  template<class L>
  class simplecontent_op_dispatcher : public simplecontent_op {
  public:
    virtual schematype_id get_schematype() const { return simplecontent_id; }
    virtual const qname& get_typename() const { return L::typename_; }
    /** creatable */
    virtual void* create() const { return L::create(); }
    virtual void destroy(void *elm) const { L::destroy(elm); }
    virtual bool equals(const void *lhs, const void *rhs) const {
      return L::equals(lhs, rhs);
    }
    virtual void copy(void *dest, const void *src) const {
      L::copy(dest, src);
    }

    /** attribute_types getter. */
    virtual const attribute_types *get_attribute_types() const { 
      return &L::attribute_types_; 
    }
    virtual const any_member *get_anyattr_type() const {
      return L::get_anyattr_type();
    }

    virtual void set_default(const char *defval) {
      L::value_type_.setup_default_value(defval);
    }

    virtual bool is_default(const void *element) const {
      return L::value_type_.is_member_default(element);
    }
    virtual const member_type& get_valuetype() const { return L::value_type_; }

  };

  template<class L, class T> 
  struct simplecontent_statics {
    static qname typename_;
    static member_type value_type_;
    static simplecontent_op_dispatcher<L> dispatcher_;
  };

  template<class L, class T>
  qname simplecontent_statics<L, T>::typename_;

  template<class L, class T>
  member_type simplecontent_statics<L, T>::value_type_;

  template<class L, class T>
  simplecontent_op_dispatcher<L> simplecontent_statics<L, T>::dispatcher_;


  template<class T, class L=xiso::leaf<T> >
  class simplecontent : public attributes<L, T>, public simplecontent_statics<L, T> {
  public:
    typedef T value_type;
    
    virtual ~simplecontent(){}
    
    static void initialize() {
      if (!system_type_registory().add(L()))
	return;
      attribute_types_.clear();
      member_getter *op = new c_style_getter(0, &nill_leaf::dispatcher_);	  
      value_type_ = member_type(op);
      L l; l.model();
    }
    static void uninitialize() {
      attribute_types_.clear();
    }

    static T* create() { 
      T* t = new T;
      simplecontent_construct(t, dispatcher_);
      return t; 
    }

    static void destroy(void *elm) { 
      simplecontent_destruct(elm, dispatcher_);
      delete static_cast<T*>(elm); 
    }

    static bool equals(const void *lhs, const void *rhs) {
      return simplecontent_equals(lhs, rhs, dispatcher_);
    }

    static void copy(void *dest, const void *src) {
      simplecontent_copy(dest, src, dispatcher_);
    }

    static element_op* get_attribute_dispatcher() { return &dispatcher_; } 
    static default_op* create_default_op() { return 0; }

    // Helper class to define serializable member.
    template<class V, class P, class VL>
    static void value(V P::* m, const VL&) {
      VL::initialize();
      member_getter *op = 
	create_c_style_getter(&VL::dispatcher_, reinterpret_cast<T*>(0), m);	  
      L::value_type_ = member_type(op); 
      default_op *defop = VL::create_default_op();
      if (defop != 0)
	value_type_.set_default_op(defop);
    }
    template<class V, class P>
    static void value(V P::* m) {
      value(m, xiso::leaf<V>());
    }
    
    static void xmltype(const char *name) {
      typeinfo_.set_name(qname(name));
    }

    static void set_default(const char *defval) {
      if (mtype_.get_schematype() != simpletype_id)
	throw internal_error();
      L::value_type_.set_default(defval);
    }
  };

} // namespace aka2

#endif /* AKAXISO_SIMPLECONTENT_H__ */
