// Copyright (c) 2013-2020, SIB - Swiss Institute of Bioinformatics and
//                          Biozentrum - University of Basel
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//   http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


/// \brief Defines helpers to convert STL objects to python objects

#ifndef PROMOD3_EXPORT_HELPERS_HH
#define PROMOD3_EXPORT_HELPERS_HH

#include <boost/python.hpp>
#include <vector>
#include <map>

namespace promod3 { namespace core {

// GT-NOTE: none of those functions were checked for efficiency!

template <typename Iterator>
void AppendToList(Iterator first, Iterator last, boost::python::list& l) {
  for (Iterator i = first; i != last; ++i) {
    l.append(*i);
  }
}

template <typename Vec>
void AppendVectorToList(const Vec& v, boost::python::list& l) {
  AppendToList(v.begin(), v.end(), l);
}

// specialization for bool-vector needed for clang support
inline void AppendVectorToList(const std::vector<bool>& v,
                               boost::python::list& l) {
  for (size_t i = 0; i < v.size(); ++i) {
    const bool b = v[i];
    l.append(b);
  }
}

template <typename T1, typename T2>
void AppendVectorToList(const std::vector<std::pair<T1, T2> >& v,
                        boost::python::list& l) {
  typedef typename std::vector<std::pair<T1, T2> >::const_iterator Iterator;
  for (Iterator i = v.begin(); i != v.end(); ++i) {
    l.append(boost::python::make_tuple(i->first,i->second));
  }
}

template <typename T>
void ConvertListToVector(const boost::python::list& l, std::vector<T>& v) {
  const int N = boost::python::len(l);
  v.clear();
  v.reserve(N);
  for (int i = 0; i < N; ++i) {
    v.push_back(boost::python::extract<T>(l[i]));
  }
}

template <typename T>
void ConvertListToCArray(const boost::python::list& l, T* v) {
  const int N = boost::python::len(l);
  for (int i = 0; i < N; ++i) {
    v[i] = boost::python::extract<T>(l[i]);
  }
}

template <typename K, typename V>
void ConvertDictToMap(const boost::python::dict& d, std::map<K,V>& m) {
  m.clear();
  boost::python::list keys = d.keys();
  for (int i = 0; i < boost::python::len(keys); ++i) {
    const K key = boost::python::extract<K>(keys[i]);
    const V value = boost::python::extract<V>(d[keys[i]]);
    m[key] = value;
  }
}

template <typename K, typename V>
void ConvertMapToDict(const std::map<K,V>& m, boost::python::dict& d) {
  typedef typename std::map<K,V>::const_iterator Iterator;
  d.clear();
  for (Iterator i = m.begin(); i != m.end(); ++i) {
    d[i->first] = i->second;
  }
}

}} // ns

#endif
