// (C) Copyright 2007 
// Douglas Gregor <doug.gregor -at- gmail.com>
// Andreas Kloeckner <inform -at- tiker.net>

// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

//  Authors: Douglas Gregor, Andreas Kloeckner

/** @file py_nonblocking.cpp
 *
 *  This file reflects the Boost.MPI nonblocking operations into Python
 *  functions.
 */

#include <vector>
#include <iterator>
#include <algorithm>
#include <boost/operators.hpp>
#include <boost/python.hpp>
#include <boost/python/stl_iterator.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/mpi.hpp>
#include "request_with_value.hpp"

using namespace std;
using namespace boost::python;
using namespace boost::mpi;




namespace
{
  template <class ValueType, class RequestIterator>
  class py_call_output_iterator :
    public boost::output_iterator_helper< 
      py_call_output_iterator<ValueType, RequestIterator> >
  {
    private:
      object m_callable;
      RequestIterator m_request_iterator;

    public:
      explicit py_call_output_iterator(object callable, 
          const RequestIterator &req_it)
        : m_callable(callable), m_request_iterator(req_it)
      { }

      py_call_output_iterator &operator=(ValueType const &v)
      {
        m_callable((m_request_iterator++)->get_value_or_none(), v);
        return *this;
      }
  };




  typedef std::vector<python::request_with_value> request_list;
  typedef py_call_output_iterator<status, request_list::iterator> 
    status_value_iterator;




  std::auto_ptr<request_list> make_request_list_from_py_list(object iterable)
  {
    std::auto_ptr<request_list> result(new request_list);
    std::copy(
        stl_input_iterator<python::request_with_value>(iterable),
        stl_input_iterator<python::request_with_value>(),
        back_inserter(*result));
    return result;
  }




  class request_list_indexing_suite :
    public vector_indexing_suite<request_list, false, request_list_indexing_suite>
  {
    public:
      // FIXME: requests are not comparable, thus __contains__ makes no sense.
      // Unfortunately, indexing_suites insist on having __contains__ available.
      // Just make it error out for now.

      static bool
        contains(request_list& container, request const& key)
        {
          PyErr_SetString(PyExc_NotImplementedError, "mpi requests are not comparable");
          throw error_already_set();
        }
  };




  void check_request_list_not_empty(const request_list &requests)
  {
    if (requests.size() == 0)
    {
      PyErr_SetString(PyExc_ValueError, "cannot wait on an empty request vector");
      throw error_already_set();
    }

  }





  object wrap_wait_any(request_list &requests)
  {
    check_request_list_not_empty(requests);

    pair<status, request_list::iterator> result = 
      wait_any(requests.begin(), requests.end());

    return make_tuple(
        result.second->get_value_or_none(),
        result.first, 
        distance(requests.begin(), result.second));
  }




  object wrap_test_any(request_list &requests)
  {
    check_request_list_not_empty(requests);
    ::boost::optional<pair<status, request_list::iterator> > result = 
      test_any(requests.begin(), requests.end());

    if (result)
      return make_tuple(
          result->second->get_value_or_none(),
          result->first, 
          distance(requests.begin(), result->second));
    else
      return object();
  }





  void wrap_wait_all(request_list &requests, object py_callable)
  {
    check_request_list_not_empty(requests);
    if (py_callable != object())
      wait_all(requests.begin(), requests.end(), 
          status_value_iterator(py_callable, requests.begin()));
    else
      wait_all(requests.begin(), requests.end());
  }




  bool wrap_test_all(request_list &requests, object py_callable)
  {
    check_request_list_not_empty(requests);
    if (py_callable != object())
      return test_all(requests.begin(), requests.end(), 
          status_value_iterator(py_callable, requests.begin()));
    else
      return test_all(requests.begin(), requests.end());
  }




  int wrap_wait_some(request_list &requests, object py_callable)
  {
    check_request_list_not_empty(requests);
    request_list::iterator first_completed;
    if (py_callable != object())
      first_completed = wait_some(requests.begin(), requests.end(), 
          status_value_iterator(py_callable, requests.begin())).second;
    else
      first_completed = wait_some(requests.begin(), requests.end());

    return distance(requests.begin(), first_completed);
  }




  int wrap_test_some(request_list &requests, object py_callable)
  {
    check_request_list_not_empty(requests);
    request_list::iterator first_completed;
    if (py_callable != object())
      first_completed = test_some(requests.begin(), requests.end(), 
          status_value_iterator(py_callable, requests.begin())).second;
    else
      first_completed = test_some(requests.begin(), requests.end());

    return distance(requests.begin(), first_completed);
  }
}




namespace boost { namespace mpi { namespace python {

extern const char* request_list_init_docstring;
extern const char* request_list_append_docstring;

extern const char* nonblocking_wait_any_docstring;
extern const char* nonblocking_test_any_docstring;
extern const char* nonblocking_wait_all_docstring;
extern const char* nonblocking_test_all_docstring;
extern const char* nonblocking_wait_some_docstring;
extern const char* nonblocking_test_some_docstring;

void export_nonblocking()
{
  using boost::python::arg;

  {
    typedef request_list cl;
    class_<cl>("RequestList", "A list of Request objects.")
      .def("__init__", make_constructor(make_request_list_from_py_list),
          /*arg("iterable"),*/ request_list_init_docstring)
      .def(request_list_indexing_suite())
      ;
  }

  def("wait_any", wrap_wait_any,
      (arg("requests")),
      nonblocking_wait_any_docstring);
  def("test_any", wrap_test_any,
      (arg("requests")),
      nonblocking_test_any_docstring);

  def("wait_all", wrap_wait_all,
      (arg("requests"), arg("callable") = object()),
      nonblocking_wait_all_docstring);
  def("test_all", wrap_test_all,
      (arg("requests"), arg("callable") = object()),
      nonblocking_test_all_docstring);

  def("wait_some", wrap_wait_some,
      (arg("requests"), arg("callable") = object()),
      nonblocking_wait_some_docstring);
  def("test_some", wrap_test_some,
      (arg("requests"), arg("callable") = object()),
      nonblocking_test_some_docstring);
}

} } }
