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

#include <akaxiso/classes/simpletype.h>
#include <akaxiso/classes/attribute.h>
#include <akaxiso/classes/closure.h>
#include <akaxiso/classes/type_registory.h>
#include <akaxiso/classes/fixed.h>
#include <akaxiso/classes/ptrmember.h>
#include <vector>

#include <akaxiso/classes/memberdef.h>

namespace aka2 {

  template<class L>
  class sequence_op_dispatcher : public sequence_op {
  public:
    virtual schematype_id get_schematype() const { return sequence_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_info getter. */
    virtual const attribute_types *get_attribute_types() const { 
      return &L::attribute_types_; 
    }
    /** sequence_info getter. */
    virtual const member_types &get_member_types() const {
      return L::member_types_;
    }
    virtual const any_member *get_anyattr_type() const { return L::get_anyattr_type(); }
  };


  template<class L, class T> 
  struct sequence_statics {
    static member_types member_types_;
    static qname typename_;
    static sequence_op_dispatcher<L> dispatcher_;
  };

  template<class L, class T>
  member_types sequence_statics<L, T>::member_types_;

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

  template<class L, class T>
  sequence_op_dispatcher<L> sequence_statics<L, T>::dispatcher_;


  template<class T, class L=xiso::leaf<T> >
  class sequence : public attributes<L, T>, 
		   public sequence_statics<L, T>,
		   public memberdef<L, T> {
  public:
    typedef T value_type;

    virtual ~sequence(){}

    static member_type* register_membertype(const member_type &mtype) { 
      member_types_.push_back(mtype); 
      return &member_types_.back();
    } 

    static void initialize() {
      if (!system_type_registory().add(L()))
      	return;
      member_types_.clear();
      attribute_types_.clear();
      L l; l.model();
    }

    static void uninitialize() {
      member_types_.clear();
      attribute_types_.clear();
    }

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

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

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

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


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

    static void xmltype(const char *name) {
      typeinfo_.set_name(qname(name));
    }

    static void enclose(const char *tagname) {
      member_type mtype = 
      	member_type(new c_style_getter(0, &enclose_op::op_)); /* !!!!!!!!!!!!! */
      mtype.set_name(tagname); 
      L::register_membertype(mtype);
    }

    static void disclose(const char *tagname) {
      member_type mtype = 
      	member_type(new c_style_getter(0, &disclose_op::op_)); /* !!!!!!!!!!!!! */
      mtype.set_name(tagname); 
      L::register_membertype(mtype);
    }
    static bool acceptable(schematype_id id) {
      return true;
    }

  };



}

#endif
