#ifndef  SERIALIZER_VALUES
#define  SERIALIZER_VALUES

#include "trace/Serializer.hpp"

#include <limits>
#include <float.h>
#include "trace/values/Values.hpp"
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/assume_abstract.hpp>
#include <trace/Serializer.hpp>
using namespace std;

//serialize in this file all kinds of Values


  
using namespace boost::serialization;

  //Value serialization methods
  
  BOOST_SERIALIZATION_SPLIT_FREE(Value)//we have 2 functions (load/save) instead of one serialize
  
  
  //we will assume that at this point,  values are correct = do not store the is_correct bit which is used only for parsing
  //we don't need to serialize Value then, which saves a lot of compilation time.
  
  
    template<class Archive>
    void save(Archive &ar,const Value& l, const unsigned int )
    {
        bool b=l.is_correct();
        ar & b;
    }
    
        template<class Archive>
    void load(Archive &ar, Value& l, const unsigned int )
    {
        bool t;
        ar &t;
        l.set_correct(t);
    }
    
    BOOST_SERIALIZATION_ASSUME_ABSTRACT(Value);//this type can be inherited by other serialized classes*/
    
    
    //telle the compiler not to be stupid when serializing these objects
    BOOST_CLASS_TRACKING(Date, track_never)
    BOOST_CLASS_TRACKING(Name, track_never)
    BOOST_CLASS_TRACKING(Color, track_never)
    BOOST_CLASS_TRACKING(Double, track_never)
    BOOST_CLASS_TRACKING(Hex, track_never)
    BOOST_CLASS_TRACKING(String, track_never)
    BOOST_CLASS_TRACKING(::Integer, track_never)
    
    //Date serialization methods
    
      BOOST_SERIALIZATION_SPLIT_FREE(Date)
      
        template<class Archive>
    void save(Archive &ar,const Date& l, const unsigned int )
    {
          ar & boost::serialization::base_object<Value>(l);
          const double d=l.get_value();
          ar & d;
    }
    
      
        template<class Archive>
    void load(Archive &ar, Date& l, const unsigned int )
    {
        ar & boost::serialization::base_object<Value>(l);
        double d;
        ar & d;
        new(&l) Date(d);
        
    }
    
    
    
        //Color serialization methods
    
      BOOST_SERIALIZATION_SPLIT_FREE(Color)
      
        template<class Archive>
    void save(Archive &ar,const Color& l, const unsigned int )
    {
          ar & boost::serialization::base_object<Value>(l);
          double r=l.get_red();
          ar & r;
          r=l.get_green();
          ar & r;
          r=l.get_blue();
          ar & r;
    }
    
      
        template<class Archive>
    void load(Archive &ar, Color& l, const unsigned int )
    {
        ar & boost::serialization::base_object<Value>(l);
        double r;
        double g;
        double b;
        ar & r;
        ar & g;
        ar & b;
        new(&l) Color(r,g,b);
    }
    
    //Double serialization methods
    BOOST_SERIALIZATION_SPLIT_FREE(Double)
      
        template<class Archive>
    void save(Archive &ar,const Double& l, const unsigned int )
    {
          ar & boost::serialization::base_object<Value>(l);
          double d=l.get_value();
          ar & d;
    }
    
      
        template<class Archive>
    void load(Archive &ar, Double& l, const unsigned int )
    {
        ar & boost::serialization::base_object<Value>(l);    
        double d;
        ar & d;
        new(&l) Double(d);
        
    }
    
    
    
    //Hex serialization methods
    BOOST_SERIALIZATION_SPLIT_FREE(Hex)
      
        template<class Archive>
    void save(Archive &ar,const Hex& l, const unsigned int )
    {
          ar & boost::serialization::base_object<Value>(l);
          unsigned int t=l.get_value();
          ar & t;
    }
    
      
        template<class Archive>
    void load(Archive &ar, Hex& l, const unsigned int )
    {
        ar & boost::serialization::base_object<Value>(l);    
        unsigned int d;
        ar & d;
        new(&l) Hex(d);
        
    }
    
    
    //Integer serialization methods
    BOOST_SERIALIZATION_SPLIT_FREE(::Integer)//boost.Integer exists and causes a conflict without ::
      
        template<class Archive>
    void save(Archive &ar,const ::Integer& l, const unsigned int )
    {
          ar & boost::serialization::base_object<Value>(l);
          int t=l.get_value();
          ar & t;
    }
    
      
        template<class Archive>
    void load(Archive &ar, ::Integer& l, const unsigned int )
    {
        ar & boost::serialization::base_object<Value>(l);   
        int d;
        ar & d;
        new(&l) ::Integer(d);
        
    }
    
    
        //String serialization methods
    BOOST_SERIALIZATION_SPLIT_FREE(String)
      
        template<class Archive>
    void save(Archive &ar,const String& l, const unsigned int )
    {
          ar & boost::serialization::base_object<Value>(l);
          std::string t=l.to_string();
          ar & t;
    }
    
      
        template<class Archive>
    void load(Archive &ar, String& l, const unsigned int )
    {
        ar & boost::serialization::base_object<Value>(l);
        std::string d;
        ar & d;
        new(&l) String(d);
        
    }
    
    
        //Name serialization methods
    BOOST_SERIALIZATION_SPLIT_FREE(Name)
      
        template<class Archive>
    void save(Archive &ar,const Name& l, const unsigned int )
    {
          ar & boost::serialization::base_object<Value>(l);
          std::string t=l.get_name();
          ar & t;
          std::string t2=l.get_alias();
          ar & t2;
    }
    
      
        template<class Archive>
    void load(Archive &ar, Name& l, const unsigned int )
    {
        ar & boost::serialization::base_object<Value>(l);
        std::string n,a;
        ar & n;
        ar & a;
        new(&l) Name(n,a);
        
    }
    
#endif
