/*
    tests/pybind11_cross_module_tests.cpp -- contains tests that require multiple modules

    Copyright (c) 2017 Jason Rhinelander <jason@imaginary.ca>

    All rights reserved. Use of this source code is governed by a
    BSD-style license that can be found in the LICENSE file.
*/

#include "pybind11_tests.h"
#include "local_bindings.h"
#include "test_exceptions.h"

#include <pybind11/stl_bind.h>

#include <numeric>
#include <utility>

PYBIND11_MODULE(pybind11_cross_module_tests, m) {
    m.doc() = "pybind11 cross-module test module";

    // test_local_bindings.py tests:
    //
    // Definitions here are tested by importing both this module and the
    // relevant pybind11_tests submodule from a test_whatever.py

    // test_load_external
    bind_local<ExternalType1>(m, "ExternalType1", py::module_local());
    bind_local<ExternalType2>(m, "ExternalType2", py::module_local());

    // test_exceptions.py
    py::register_local_exception<LocalSimpleException>(m, "LocalSimpleException");
    m.def("raise_runtime_error", []() { PyErr_SetString(PyExc_RuntimeError, "My runtime error"); throw py::error_already_set(); });
    m.def("raise_value_error", []() { PyErr_SetString(PyExc_ValueError, "My value error"); throw py::error_already_set(); });
    m.def("throw_pybind_value_error", []() { throw py::value_error("pybind11 value error"); });
    m.def("throw_pybind_type_error", []() { throw py::type_error("pybind11 type error"); });
    m.def("throw_stop_iteration", []() { throw py::stop_iteration(); });
    m.def("throw_local_error", []() { throw LocalException("just local"); });
    m.def("throw_local_simple_error", []() { throw LocalSimpleException("external mod"); });
    py::register_exception_translator([](std::exception_ptr p) {
      try {
          if (p) std::rethrow_exception(p);
      } catch (const shared_exception &e) {
          PyErr_SetString(PyExc_KeyError, e.what());
      }
    });

    // translate the local exception into a key error but only in this module
    py::register_local_exception_translator([](std::exception_ptr p) {
      try {
          if (p) {
            std::rethrow_exception(p);
          }
      } catch (const LocalException &e) {
        PyErr_SetString(PyExc_KeyError, e.what());
      }
    });

    // test_local_bindings.py
    // Local to both:
    bind_local<LocalType, 1>(m, "LocalType", py::module_local())
        .def("get2", [](LocalType &t) { return t.i + 2; })
        ;

    // Can only be called with our python type:
    m.def("local_value", [](LocalType &l) { return l.i; });

    // test_nonlocal_failure
    // This registration will fail (global registration when LocalFail is already registered
    // globally in the main test module):
    m.def("register_nonlocal", [m]() {
        bind_local<NonLocalType, 0>(m, "NonLocalType");
    });

    // test_stl_bind_local
    // stl_bind.h binders defaults to py::module_local if the types are local or converting:
    py::bind_vector<LocalVec>(m, "LocalVec");
    py::bind_map<LocalMap>(m, "LocalMap");

    // test_stl_bind_global
    // and global if the type (or one of the types, for the map) is global (so these will fail,
    // assuming pybind11_tests is already loaded):
    m.def("register_nonlocal_vec", [m]() {
        py::bind_vector<NonLocalVec>(m, "NonLocalVec");
    });
    m.def("register_nonlocal_map", [m]() {
        py::bind_map<NonLocalMap>(m, "NonLocalMap");
    });
    // The default can, however, be overridden to global using `py::module_local()` or
    // `py::module_local(false)`.
    // Explicitly made local:
    py::bind_vector<NonLocalVec2>(m, "NonLocalVec2", py::module_local());
    // Explicitly made global (and so will fail to bind):
    m.def("register_nonlocal_map2", [m]() {
        py::bind_map<NonLocalMap2>(m, "NonLocalMap2", py::module_local(false));
    });

    // test_mixed_local_global
    // We try this both with the global type registered first and vice versa (the order shouldn't
    // matter).
    m.def("register_mixed_global_local", [m]() {
        bind_local<MixedGlobalLocal, 200>(m, "MixedGlobalLocal", py::module_local());
    });
    m.def("register_mixed_local_global", [m]() {
        bind_local<MixedLocalGlobal, 2000>(m, "MixedLocalGlobal", py::module_local(false));
    });
    m.def("get_mixed_gl", [](int i) { return MixedGlobalLocal(i); });
    m.def("get_mixed_lg", [](int i) { return MixedLocalGlobal(i); });

    // test_internal_locals_differ
    m.def("local_cpp_types_addr", []() { return (uintptr_t) &py::detail::get_local_internals().registered_types_cpp; });

    // test_stl_caster_vs_stl_bind
    py::bind_vector<std::vector<int>>(m, "VectorInt");

    m.def("load_vector_via_binding", [](std::vector<int> &v) {
        return std::accumulate(v.begin(), v.end(), 0);
    });

    // test_cross_module_calls
    m.def("return_self", [](LocalVec *v) { return v; });
    m.def("return_copy", [](const LocalVec &v) { return LocalVec(v); });

    class Dog : public pets::Pet {
    public:
        explicit Dog(std::string name) : Pet(std::move(name)) {}
    };
    py::class_<pets::Pet>(m, "Pet", py::module_local())
        .def("name", &pets::Pet::name);
    // Binding for local extending class:
    py::class_<Dog, pets::Pet>(m, "Dog")
        .def(py::init<std::string>());
    m.def("pet_name", [](pets::Pet &p) { return p.name(); });

    py::class_<MixGL>(m, "MixGL", py::module_local()).def(py::init<int>());
    m.def("get_gl_value", [](MixGL &o) { return o.i + 100; });

    py::class_<MixGL2>(m, "MixGL2", py::module_local()).def(py::init<int>());

    // test_vector_bool
    // We can't test both stl.h and stl_bind.h conversions of `std::vector<bool>` within
    // the same module (it would be an ODR violation). Therefore `bind_vector` of `bool`
    // is defined here and tested in `test_stl_binders.py`.
    py::bind_vector<std::vector<bool>>(m, "VectorBool");

    // test_missing_header_message
    // The main module already includes stl.h, but we need to test the error message
    // which appears when this header is missing.
    m.def("missing_header_arg", [](const std::vector<float> &) {});
    m.def("missing_header_return", []() { return std::vector<float>(); });
}
