#ifndef ESORTEDARRAYOF_H
#define ESORTEDARRAYOF_H

#include "eutils.h"

#include "esortedarrayof_dec.h"
#include "evar_dec.h"

template <class T,class K>
void esortedarrayof<T,K>::addvar(evar& evarkey,evar& var)
{
  var.retain();
  addref(evarkey.get<K>(),&var.get<T>());
}
template <class T,class K>
evar esortedarrayof<T,K>::getvar(size_t i) const
{
  return(evar((T&)values(i)));
//  return(evar(values(i)));
}
template <class T,class K>
evar esortedarrayof<T,K>::getvarByKey(const evar& var) const
{
  if (var.getTypeid()==typeid(K))
    return(evar((T&)esortedarrayof<T,K>::at(var.get<K>())));
  return(evar());
}
template <class T,class K>
evar esortedarrayof<T,K>::getvarkey(size_t i) const
{
  return(evar((K&)keys(i)));
}

template <>
void esortedarrayof<evar,evar>::addvar(evar& key,evar& var);
template <>
evar esortedarrayof<evar,evar>::getvar(size_t i) const;
template <>
evar esortedarrayof<evar,evar>::getvarByKey(const evar& key) const;
template <>
evar esortedarrayof<evar,evar>::getvarkey(size_t i) const;


#include "eintarray.h"

template <class T,class K>
eintarray esortedarrayof<T,K>::findall(const T& value,size_t i,bool (*match)(const T* const &a,const T* const &b)) const
    { return( _values.findall(&value,i,match) ); }

template <class T,class K>
eintarray esortedarrayof<T,K>::findall(const esortedarrayof<T,K>& value,size_t i,bool (*match)(const T* const &a,const T* const &b)) const
    { return( _values.findall(value._values,i,match) ); }

template <class T,class K>
eintarray esortedarrayof<T,K>::findkeyall(const K& key,size_t i,bool (*match)(const K* const &a,const K* const &b)) const
    { return( _keys.findall(key,i,match) ); }

template <class T,class K>
eintarray esortedarrayof<T,K>::findkeyall(const esortedarrayof<T,K>& keys,size_t i,bool (*match)(const K* const &a,const K* const &b)) const
    { return( _keys.findall(keys._keys,i,match) ); }


template <class T,class K>
bool esortedarrayof<T,K>::equal(T* const &a, T* const &b)
  { return(*a==*b); }

template <class T,class K>
bool esortedarrayof<T,K>::equalkey(K* const &a,K* const &b)
  { if (!a || !b) return(false); return(*a == *b); }



template <class T,class K>
ostream& operator<<(ostream& stream,const esortedarrayof<T,K>& var)
{
  stream<<"{ "<<endl;
  size_t i;

  if (var.size()){
    for (i=0; i<var.size()-1; ++i){
      stream<<var.keys(i)<<" = ";
      stream<<var.values(i)<<", "<<endl;
    }
    stream<<var.keys(i)<<" = ";
    stream<<var.values(i)<<endl;
  }
  stream<<" }";
  return(stream);
}

template <class T,class K>
esortedarrayof<T,K>::esortedarrayof()
{
}

template <class T,class K>
esortedarrayof<T,K>::esortedarrayof(const esortedarrayof<T,K>& a)
{
  *this = a;
}

/*
template <class T,class K>
esortedarrayof<T,K>::esortedarrayof(const ebasicarray<T> &a)
{
  add(a);
}
*/

template <class T,class K>
esortedarrayof<T,K>::esortedarrayof(const T& a)
{
  add(a);
}

template <class T,class K>
esortedarrayof<T,K>::~esortedarrayof()
{
  clear();
}

template <class T,class K>
T& esortedarrayof<T,K>::addref(const K& key,T *value)
{
  _map.insert(pair<K,T>(new K(key),value));
  return(*_value);
}

template <class T,class K>
T& esortedarrayof<T,K>::add(const K& key,const T& value)
{
  T *nvalue=new T(value);
  _map.insert(pair<K,T>(new K(key),nvalue));
  return(*nvalue);
}

template <class T,class K>
const T& esortedarrayof<T,K>::operator[](size_t i) const
{
  return(*_values[i]);
}

template <class T,class K>
T& esortedarrayof<T,K>::operator[](size_t i)
{
  map<K,T>::iterator it=_map.begin()+i;
  return(*(it->second));
}

template <class T,class K>
const T& esortedarrayof<T,K>::operator[](const K& key) const
{
  return(*_map.at(key));
}

template <class T,class K>
T& esortedarrayof<T,K>::operator[](const K& key)
{
  if (_map.count(key)==0){
    T *nvalue=new T;
    _map[key]=nvalue;
    return(*nvalue);
  }
  return(*_map[key]);
}

template <class T,class K>
const T& esortedarrayof<T,K>::at(const K& key) const
{
  return(*_map.at(key));
}

template <class T,class K>
T& esortedarrayof<T,K>::at(const K& key)
{
  return(*_map.at(key));
}

template <class T,class K>
esortedarrayof<T,K> &esortedarrayof<T,K>::operator=(const esortedarrayof<T,K>& a)
{
  if (this==&a) return(*this);
  _map = a._map;
  return(*this);
}


template <class T,class K>
void esortedarrayof<T,K>::remove(size_t i)
{
  map<K,T>::iterator it=_map.begin()+i;
  delete it->second;
  _map.erase(it);
}

template <class T,class K>
void esortedarrayof<T,K>::clear()
{
  for (map<K,T>::iterator it=_map.begin(); it!=_map.end(); ++it)
    delete it->second;
  _map.clear();
}

#endif

