// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.

#ifndef tools_sg_sf_vec
#define tools_sg_sf_vec

#include "sf"

#include "../tokenize"

namespace tools {
namespace sg {

template <class T,class TT>  //exa sf_vec<colorf,float>
class sf_vec : public bsf<T> {
  typedef bsf<T> parent;
public:
  static const std::string& s_class() {
    static const std::string s_v("tools::sg::sf_vec<"+stype(T())+","+stype(TT())+">");
    return s_v;
  }
  virtual void* cast(const std::string& a_class) const {
    if(void* p = cmp_cast< sf_vec<T,TT> >(this,a_class)) {return p;}
    return parent::cast(a_class);
  }
  virtual const std::string& s_cls() const {return s_class();}
public:
  virtual bool write(io::iwbuf& a_buffer) {
    const T& vec = parent::m_value;
    const TT* d = get_data(vec);
    return a_buffer.write_vec(vec.size(),d);
  }
  virtual bool read(io::irbuf& a_buffer) {
    T& vec = parent::m_value;
    uint32 n;
    TT* v;
    if(!a_buffer.read_vec(n,v)) {
      return false;
    }
    if(n!=vec.size()) {
      delete [] v;
      return false;
    }
    for(uint32 index=0;index<n;index++) vec[index] = v[index];
    delete [] v;
    return true;
  }
  virtual bool dump(std::ostream& a_out) {
    a_out << parent::m_value << std::endl;
    return true;
  }
  virtual bool s_value(std::string& a_s) const {
    a_s.clear();
    const T& vec = parent::m_value;
    for(size_t index=0;index<vec.size();index++) {
      if(index) a_s += ' ';
      std::ostringstream strm;
      strm << vec[index];
      a_s += strm.str();
    }
    return true;
  }
  virtual bool s2value(const std::string& a_s) {
    std::vector<std::string> ws;
    words(a_s," ",false,ws);
    T& vec = parent::m_value;
    if(ws.size()!=vec.size()) return false;
    T old_vec = vec;
    for(size_t index=0;index<vec.size();index++) {
      std::istringstream strm(ws[index].c_str());
      TT v;
      strm >> v;
      if(strm.fail()) {
        vec = old_vec;
        return false;
      }
      if(vec[index]!=v) parent::m_touched = true;
      vec[index] = v;
    }
    return true;
  }
public:
  sf_vec():parent(){}
  sf_vec(const T& a_value):parent(a_value){}
  virtual ~sf_vec(){}
public:
  sf_vec(const sf_vec& a_from)
  :parent(a_from){}
  sf_vec& operator=(const sf_vec& a_from){
    parent::operator=(a_from);
    return *this;
  }
public:
  sf_vec& operator=(const T& a_value){
    parent::operator=(a_value);
    return *this;
  }
  sf_vec& operator+=(const T& a_value) {
    parent::value(parent::value()+a_value);
    return *this;
  }
};

}}

#endif
