/*
    tests/test_stl_binders.cpp -- Usage of stl_binders functions

    Copyright (c) 2016 Sergey Lyskov

    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/numpy.h>
#include <pybind11/stl_bind.h>

#include "pybind11_tests.h"

#include <deque>
#include <map>
#include <unordered_map>

class El {
public:
    El() = delete;
    explicit El(int v) : a(v) {}

    int a;
};

std::ostream &operator<<(std::ostream &s, El const &v) {
    s << "El{" << v.a << '}';
    return s;
}

/// Issue #487: binding std::vector<E> with E non-copyable
class E_nc {
public:
    explicit E_nc(int i) : value{i} {}
    E_nc(const E_nc &) = delete;
    E_nc &operator=(const E_nc &) = delete;
    E_nc(E_nc &&) = default;
    E_nc &operator=(E_nc &&) = default;

    int value;
};

template <class Container>
Container *one_to_n(int n) {
    auto *v = new Container();
    for (int i = 1; i <= n; i++) {
        v->emplace_back(i);
    }
    return v;
}

template <class Map>
Map *times_ten(int n) {
    auto *m = new Map();
    for (int i = 1; i <= n; i++) {
        m->emplace(int(i), E_nc(10 * i));
    }
    return m;
}

template <class NestMap>
NestMap *times_hundred(int n) {
    auto *m = new NestMap();
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            (*m)[i].emplace(int(j * 10), E_nc(100 * j));
        }
    }
    return m;
}

TEST_SUBMODULE(stl_binders, m) {
    // test_vector_int
    py::bind_vector<std::vector<unsigned int>>(m, "VectorInt", py::buffer_protocol());

    // test_vector_custom
    py::class_<El>(m, "El").def(py::init<int>());
    py::bind_vector<std::vector<El>>(m, "VectorEl");
    py::bind_vector<std::vector<std::vector<El>>>(m, "VectorVectorEl");

    // test_map_string_double
    py::bind_map<std::map<std::string, double>>(m, "MapStringDouble");
    py::bind_map<std::unordered_map<std::string, double>>(m, "UnorderedMapStringDouble");

    // test_map_string_double_const
    py::bind_map<std::map<std::string, double const>>(m, "MapStringDoubleConst");
    py::bind_map<std::unordered_map<std::string, double const>>(m,
                                                                "UnorderedMapStringDoubleConst");

    py::class_<E_nc>(m, "ENC").def(py::init<int>()).def_readwrite("value", &E_nc::value);

    // test_noncopyable_containers
    py::bind_vector<std::vector<E_nc>>(m, "VectorENC");
    m.def("get_vnc", &one_to_n<std::vector<E_nc>>);
    py::bind_vector<std::deque<E_nc>>(m, "DequeENC");
    m.def("get_dnc", &one_to_n<std::deque<E_nc>>);
    py::bind_map<std::map<int, E_nc>>(m, "MapENC");
    m.def("get_mnc", &times_ten<std::map<int, E_nc>>);
    py::bind_map<std::unordered_map<int, E_nc>>(m, "UmapENC");
    m.def("get_umnc", &times_ten<std::unordered_map<int, E_nc>>);
    // Issue #1885: binding nested std::map<X, Container<E>> with E non-copyable
    py::bind_map<std::map<int, std::vector<E_nc>>>(m, "MapVecENC");
    m.def("get_nvnc", [](int n) {
        auto *m = new std::map<int, std::vector<E_nc>>();
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                (*m)[i].emplace_back(j);
            }
        }
        return m;
    });
    py::bind_map<std::map<int, std::map<int, E_nc>>>(m, "MapMapENC");
    m.def("get_nmnc", &times_hundred<std::map<int, std::map<int, E_nc>>>);
    py::bind_map<std::unordered_map<int, std::unordered_map<int, E_nc>>>(m, "UmapUmapENC");
    m.def("get_numnc", &times_hundred<std::unordered_map<int, std::unordered_map<int, E_nc>>>);

    // test_vector_buffer
    py::bind_vector<std::vector<unsigned char>>(m, "VectorUChar", py::buffer_protocol());
    // no dtype declared for this version:
    struct VUndeclStruct {
        bool w;
        uint32_t x;
        double y;
        bool z;
    };
    m.def("create_undeclstruct", [m]() mutable {
        py::bind_vector<std::vector<VUndeclStruct>>(
            m, "VectorUndeclStruct", py::buffer_protocol());
    });

    // The rest depends on numpy:
    try {
        py::module_::import("numpy");
    } catch (...) {
        return;
    }

    // test_vector_buffer_numpy
    struct VStruct {
        bool w;
        uint32_t x;
        double y;
        bool z;
    };
    PYBIND11_NUMPY_DTYPE(VStruct, w, x, y, z);
    py::class_<VStruct>(m, "VStruct").def_readwrite("x", &VStruct::x);
    py::bind_vector<std::vector<VStruct>>(m, "VectorStruct", py::buffer_protocol());
    m.def("get_vectorstruct", [] {
        return std::vector<VStruct>{{false, 5, 3.0, true}, {true, 30, -1e4, false}};
    });
}
