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

#include <akaxiso/classes/traits.h>
#include <akaxiso/classes/construct.h>
#include <akaxiso/classes/destruct.h>
#include <akaxiso/classes/copy.h>

#include <typeinfo>

namespace aka2 {

  template<class V, class VL=xiso::leaf<V> >
  struct default_value : public default_op {
    typedef V value_type;
    
    default_value() : has_default_(false) {}
    virtual ~default_value(){}

    virtual void set_default(const char *defval) {
      std::istringstream istm(defval);
      VL::read_text(&default_, istm, system_global_attributes());
      has_default_ = true;
    }

    virtual bool is_default(const void *v) const {
      if (has_default_)
        return VL::equals(v, &default_);
      return false;
    }

    virtual bool is_default_string(const std::string &val) const {
      assert(has_default_);
      value_type v;
      try {
	std::istringstream istm(val);
	VL::read_text(&v, istm, system_global_attributes());
      }
      catch ( ... ) {
	return false;
      }
      return (v == default_);
    }

    virtual bool has_default() const {
      return has_default_;
    }

    virtual void init_value(void *elm) const {
      VL::copy(elm, &default_);
    }

    virtual void write_default(std::ostream &ostm) const {
      ostm << default_;
    }

  private:
    V default_;
    bool has_default_;
  };


  template<class L>
  struct simpletype_op_dispatcher : public simpletype_op {
  public:
    virtual schematype_id get_schematype() const { return simpletype_id; }
    virtual const qname& get_typename() const { return L::typename_; }
    virtual const attribute_types *get_attribute_types() const { return 0; } 

    virtual void write_text(const void* elm, 
			    std::ostream &ostm, 
			    const global_attributes &gattrs) const {
      L::write_text(elm, ostm, gattrs);
    }

    virtual void read_text(void* elm, std::istringstream &istm, 
			   const global_attributes &gattrs) const {
      L::read_text(elm, istm, gattrs);
    }

    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);
    }
  };


  template<class L, class V>
  struct simpletype_statics {
    static simpletype_op_dispatcher<L> dispatcher_;
    static qname typename_;
  };

  template<class L, class V>
  simpletype_op_dispatcher<L> simpletype_statics<L, V>::dispatcher_;

  template<class L, class V>
  qname simpletype_statics<L, V>::typename_;




  template<class V, class L=xiso::leaf<V> >
    class simpletype : public simpletype_statics<L, V> {
  public:
    virtual ~simpletype(){}

    static void initialize() {  
      system_type_registory().add(L());
    }
    static void uninitialize() {}

    static void write_text(const void *elm, std::ostream &ostm, 
			   const global_attributes &gattrs) {
      const V &value = *reinterpret_cast<const V*>(elm);
      ostm << value;
    }

    static void read_text(void *elm, std::istringstream &istm, 
			  const global_attributes &gattrs) {
      V &value = *reinterpret_cast<V*>(elm);
      istm >> value;
      if (istm.fail())
      	throw parse_exception(__FILE__, __LINE__, "Failed to parse simpletype value.");
    }

    static void *create() { 
      V* v = new V;
      return v; 
    }
    static void destroy(void *elm) { delete static_cast<V*>(elm); }
    static bool equals(const void *lhs, const void *rhs) {
      return *static_cast<const V*>(lhs) == *static_cast<const V*>(rhs);
    }

    static void copy(void *dest, const void *src) {
      const V &srcv = *static_cast<const V*>(src);
      V &dstv = *static_cast<V*>(dest);
      dstv = srcv;
    }

    static default_op* create_default_op() { return new default_value<V>; }
    static simpletype_op_dispatcher<L> *get_attribute_dispatcher() { return &dispatcher_; }
  };


  struct nill {  };
  
  struct  nill_leaf :  public aka2::simpletype<nill, nill_leaf>  {
    static void initialize() {}
    static void uninitialize() {}
    static void *create() { return new nill; }
    static void destroy(void *e) { delete static_cast<nill*>(e);}
    static bool equals(const void *, const void *) {
      return true;
    }
    static void write_text(const void *e, std::ostream &ostm, const global_attributes &gattrs) {}
    static void read_text(void *e, std::istringstream &istm, const global_attributes &gattrs) { }
    static default_op* create_default_op() { return 0; }
  };


}

#endif
