// WARNING: Please don't edit this file. It was generated by Python/WinRT v1.0.0-alpha.6

#pragma once

#include "pybase.h"

#if __has_include("py.Windows.Foundation.h")
#include "py.Windows.Foundation.h"
#endif

#include <winrt/Windows.Foundation.Collections.h>

namespace py::proj::Windows::Foundation::Collections
{
    struct IIterable
    {
        virtual ~IIterable() {};
        virtual winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept = 0;
        virtual std::size_t hash() noexcept = 0;
        virtual PyObject* First(PyObject*) noexcept = 0;
        virtual PyObject* dunder_iter() noexcept = 0;
    };

    struct IIterator
    {
        virtual ~IIterator() {};
        virtual winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept = 0;
        virtual std::size_t hash() noexcept = 0;
        virtual PyObject* MoveNext(PyObject*) noexcept = 0;
        virtual PyObject* GetMany(PyObject*) noexcept = 0;
        virtual PyObject* get_Current() noexcept = 0;
        virtual PyObject* get_HasCurrent() noexcept = 0;
        virtual PyObject* dunder_iter() noexcept = 0;
        virtual PyObject* dunder_iternext() noexcept = 0;
    };

    struct IKeyValuePair
    {
        virtual ~IKeyValuePair() {};
        virtual winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept = 0;
        virtual std::size_t hash() noexcept = 0;
        virtual PyObject* get_Key() noexcept = 0;
        virtual PyObject* get_Value() noexcept = 0;
    };

    struct IMapChangedEventArgs
    {
        virtual ~IMapChangedEventArgs() {};
        virtual winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept = 0;
        virtual std::size_t hash() noexcept = 0;
        virtual PyObject* get_CollectionChange() noexcept = 0;
        virtual PyObject* get_Key() noexcept = 0;
    };

    struct IMapView
    {
        virtual ~IMapView() {};
        virtual winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept = 0;
        virtual std::size_t hash() noexcept = 0;
        virtual PyObject* Lookup(PyObject*) noexcept = 0;
        virtual PyObject* HasKey(PyObject*) noexcept = 0;
        virtual PyObject* Split(PyObject*) noexcept = 0;
        virtual PyObject* First(PyObject*) noexcept = 0;
        virtual PyObject* get_Size() noexcept = 0;
        virtual PyObject* dunder_iter() noexcept = 0;
        virtual Py_ssize_t map_length() noexcept = 0;
        virtual PyObject* map_subscript(PyObject* key) noexcept = 0;
    };

    struct IMap
    {
        virtual ~IMap() {};
        virtual winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept = 0;
        virtual std::size_t hash() noexcept = 0;
        virtual PyObject* Lookup(PyObject*) noexcept = 0;
        virtual PyObject* HasKey(PyObject*) noexcept = 0;
        virtual PyObject* GetView(PyObject*) noexcept = 0;
        virtual PyObject* Insert(PyObject*) noexcept = 0;
        virtual PyObject* Remove(PyObject*) noexcept = 0;
        virtual PyObject* Clear(PyObject*) noexcept = 0;
        virtual PyObject* First(PyObject*) noexcept = 0;
        virtual PyObject* get_Size() noexcept = 0;
        virtual PyObject* dunder_iter() noexcept = 0;
        virtual Py_ssize_t map_length() noexcept = 0;
        virtual PyObject* map_subscript(PyObject* key) noexcept = 0;
        virtual int map_assign(PyObject* key, PyObject* value) noexcept = 0;
    };

    struct IObservableMap
    {
        virtual ~IObservableMap() {};
        virtual winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept = 0;
        virtual std::size_t hash() noexcept = 0;
        virtual PyObject* Lookup(PyObject*) noexcept = 0;
        virtual PyObject* HasKey(PyObject*) noexcept = 0;
        virtual PyObject* GetView(PyObject*) noexcept = 0;
        virtual PyObject* Insert(PyObject*) noexcept = 0;
        virtual PyObject* Remove(PyObject*) noexcept = 0;
        virtual PyObject* Clear(PyObject*) noexcept = 0;
        virtual PyObject* First(PyObject*) noexcept = 0;
        virtual PyObject* get_Size() noexcept = 0;
        virtual PyObject* add_MapChanged(PyObject*) noexcept = 0;
        virtual PyObject* remove_MapChanged(PyObject*) noexcept = 0;
        virtual PyObject* dunder_iter() noexcept = 0;
        virtual Py_ssize_t map_length() noexcept = 0;
        virtual PyObject* map_subscript(PyObject* key) noexcept = 0;
        virtual int map_assign(PyObject* key, PyObject* value) noexcept = 0;
    };

    struct IObservableVector
    {
        virtual ~IObservableVector() {};
        virtual winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept = 0;
        virtual std::size_t hash() noexcept = 0;
        virtual PyObject* GetAt(PyObject*) noexcept = 0;
        virtual PyObject* GetView(PyObject*) noexcept = 0;
        virtual PyObject* IndexOf(PyObject*) noexcept = 0;
        virtual PyObject* SetAt(PyObject*) noexcept = 0;
        virtual PyObject* InsertAt(PyObject*) noexcept = 0;
        virtual PyObject* RemoveAt(PyObject*) noexcept = 0;
        virtual PyObject* Append(PyObject*) noexcept = 0;
        virtual PyObject* RemoveAtEnd(PyObject*) noexcept = 0;
        virtual PyObject* Clear(PyObject*) noexcept = 0;
        virtual PyObject* GetMany(PyObject*) noexcept = 0;
        virtual PyObject* ReplaceAll(PyObject*) noexcept = 0;
        virtual PyObject* First(PyObject*) noexcept = 0;
        virtual PyObject* get_Size() noexcept = 0;
        virtual PyObject* add_VectorChanged(PyObject*) noexcept = 0;
        virtual PyObject* remove_VectorChanged(PyObject*) noexcept = 0;
        virtual PyObject* dunder_iter() noexcept = 0;
        virtual Py_ssize_t seq_length() noexcept = 0;
        virtual PyObject* seq_item(Py_ssize_t i) noexcept = 0;
        virtual int seq_assign(Py_ssize_t i, PyObject* value) noexcept = 0;
    };

    struct IVectorView
    {
        virtual ~IVectorView() {};
        virtual winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept = 0;
        virtual std::size_t hash() noexcept = 0;
        virtual PyObject* GetAt(PyObject*) noexcept = 0;
        virtual PyObject* IndexOf(PyObject*) noexcept = 0;
        virtual PyObject* GetMany(PyObject*) noexcept = 0;
        virtual PyObject* First(PyObject*) noexcept = 0;
        virtual PyObject* get_Size() noexcept = 0;
        virtual PyObject* dunder_iter() noexcept = 0;
        virtual Py_ssize_t seq_length() noexcept = 0;
        virtual PyObject* seq_item(Py_ssize_t i) noexcept = 0;
    };

    struct IVector
    {
        virtual ~IVector() {};
        virtual winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept = 0;
        virtual std::size_t hash() noexcept = 0;
        virtual PyObject* GetAt(PyObject*) noexcept = 0;
        virtual PyObject* GetView(PyObject*) noexcept = 0;
        virtual PyObject* IndexOf(PyObject*) noexcept = 0;
        virtual PyObject* SetAt(PyObject*) noexcept = 0;
        virtual PyObject* InsertAt(PyObject*) noexcept = 0;
        virtual PyObject* RemoveAt(PyObject*) noexcept = 0;
        virtual PyObject* Append(PyObject*) noexcept = 0;
        virtual PyObject* RemoveAtEnd(PyObject*) noexcept = 0;
        virtual PyObject* Clear(PyObject*) noexcept = 0;
        virtual PyObject* GetMany(PyObject*) noexcept = 0;
        virtual PyObject* ReplaceAll(PyObject*) noexcept = 0;
        virtual PyObject* First(PyObject*) noexcept = 0;
        virtual PyObject* get_Size() noexcept = 0;
        virtual PyObject* dunder_iter() noexcept = 0;
        virtual Py_ssize_t seq_length() noexcept = 0;
        virtual PyObject* seq_item(Py_ssize_t i) noexcept = 0;
        virtual int seq_assign(Py_ssize_t i, PyObject* value) noexcept = 0;
    };
}

namespace py::impl::Windows::Foundation::Collections
{
    template <typename K, typename V>
    struct MapChangedEventHandler
    {
        static winrt::Windows::Foundation::Collections::MapChangedEventHandler<K, V> get(PyObject* callable)
        {
            py::delegate_callable _delegate{ callable };

            return [delegate = std::move(_delegate)](auto param0, auto param1)
            {
                winrt::handle_type<py::gil_state_traits> gil_state{ PyGILState_Ensure() };

                py::pyobj_handle py_param0{ py::convert(param0) };
                py::pyobj_handle py_param1{ py::convert(param1) };

                py::pyobj_handle args{ PyTuple_Pack(2, py_param0.get(), py_param1.get()) };
                py::pyobj_handle return_value{ PyObject_CallObject(delegate.callable(), args.get()) };

                if (!return_value)
                {
                    PyErr_WriteUnraisable(delegate.callable());
                    throw winrt::hresult_invalid_argument();
                }
            };
        };
    };

    template <typename T>
    struct VectorChangedEventHandler
    {
        static winrt::Windows::Foundation::Collections::VectorChangedEventHandler<T> get(PyObject* callable)
        {
            py::delegate_callable _delegate{ callable };

            return [delegate = std::move(_delegate)](auto param0, auto param1)
            {
                winrt::handle_type<py::gil_state_traits> gil_state{ PyGILState_Ensure() };

                py::pyobj_handle py_param0{ py::convert(param0) };
                py::pyobj_handle py_param1{ py::convert(param1) };

                py::pyobj_handle args{ PyTuple_Pack(2, py_param0.get(), py_param1.get()) };
                py::pyobj_handle return_value{ PyObject_CallObject(delegate.callable(), args.get()) };

                if (!return_value)
                {
                    PyErr_WriteUnraisable(delegate.callable());
                    throw winrt::hresult_invalid_argument();
                }
            };
        };
    };

    template<typename T>
    struct IIterable : public py::proj::Windows::Foundation::Collections::IIterable
    {
        IIterable(winrt::Windows::Foundation::Collections::IIterable<T> o) : _obj(o) {}
        winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept override { return _obj; }
        std::size_t hash() noexcept override { return py::get_instance_hash(_obj); }
        PyObject* First(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    return py::convert(_obj.First());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* dunder_iter() noexcept override
        {
            try
            {
                return py::convert(_obj.First());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }

        winrt::Windows::Foundation::Collections::IIterable<T> _obj{ nullptr };
    };

    template<typename T>
    struct IIterator : public py::proj::Windows::Foundation::Collections::IIterator
    {
        IIterator(winrt::Windows::Foundation::Collections::IIterator<T> o) : _obj(o) {}
        winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept override { return _obj; }
        std::size_t hash() noexcept override { return py::get_instance_hash(_obj); }
        PyObject* GetMany(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0_count = py::convert_to<winrt::com_array<T>::size_type>(args, 0);
                    winrt::com_array<T> param0 ( param0_count, py::empty_instance<T>::get() );

                    auto return_value = _obj.GetMany(param0);

                    py::pyobj_handle out_return_value{ py::convert(return_value) };
                    if (!out_return_value)
                    {
                        return nullptr;
                    }
                    py::pyobj_handle out0{ py::convert(param0) };
                    if (!out0)
                    {
                        return nullptr;
                    }
                    return PyTuple_Pack(2, out_return_value.get(), out0.get());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* MoveNext(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    return py::convert(_obj.MoveNext());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* get_Current() noexcept override
        {
            try
            {
                return py::convert(_obj.Current());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        PyObject* get_HasCurrent() noexcept override
        {
            try
            {
                return py::convert(_obj.HasCurrent());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        PyObject* dunder_iter() noexcept override
        {
            return reinterpret_cast<PyObject*>(this);
        }
        PyObject* dunder_iternext() noexcept override
        {
            try
            {
                if (_obj.HasCurrent())
                {
                    auto cur = _obj.Current();
                    _obj.MoveNext();
                    return py::convert(cur);
                }
                else
                {
                    return nullptr;
                }}
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }

        winrt::Windows::Foundation::Collections::IIterator<T> _obj{ nullptr };
    };

    template<typename K, typename V>
    struct IKeyValuePair : public py::proj::Windows::Foundation::Collections::IKeyValuePair
    {
        IKeyValuePair(winrt::Windows::Foundation::Collections::IKeyValuePair<K, V> o) : _obj(o) {}
        winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept override { return _obj; }
        std::size_t hash() noexcept override { return py::get_instance_hash(_obj); }
        PyObject* get_Key() noexcept override
        {
            try
            {
                return py::convert(_obj.Key());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        PyObject* get_Value() noexcept override
        {
            try
            {
                return py::convert(_obj.Value());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }

        winrt::Windows::Foundation::Collections::IKeyValuePair<K, V> _obj{ nullptr };
    };

    template<typename K>
    struct IMapChangedEventArgs : public py::proj::Windows::Foundation::Collections::IMapChangedEventArgs
    {
        IMapChangedEventArgs(winrt::Windows::Foundation::Collections::IMapChangedEventArgs<K> o) : _obj(o) {}
        winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept override { return _obj; }
        std::size_t hash() noexcept override { return py::get_instance_hash(_obj); }
        PyObject* get_CollectionChange() noexcept override
        {
            try
            {
                return py::convert(_obj.CollectionChange());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        PyObject* get_Key() noexcept override
        {
            try
            {
                return py::convert(_obj.Key());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }

        winrt::Windows::Foundation::Collections::IMapChangedEventArgs<K> _obj{ nullptr };
    };

    template<typename K, typename V>
    struct IMapView : public py::proj::Windows::Foundation::Collections::IMapView
    {
        IMapView(winrt::Windows::Foundation::Collections::IMapView<K, V> o) : _obj(o) {}
        winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept override { return _obj; }
        std::size_t hash() noexcept override { return py::get_instance_hash(_obj); }
        PyObject* First(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    return py::convert(_obj.First());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* HasKey(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<K>(args, 0);

                    return py::convert(_obj.HasKey(param0));
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* Lookup(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<K>(args, 0);

                    return py::convert(_obj.Lookup(param0));
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* Split(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    winrt::Windows::Foundation::Collections::IMapView<K, V> param0 { nullptr };
                    winrt::Windows::Foundation::Collections::IMapView<K, V> param1 { nullptr };

                    _obj.Split(param0, param1);

                    py::pyobj_handle out0{ py::convert(param0) };
                    if (!out0)
                    {
                        return nullptr;
                    }
                    py::pyobj_handle out1{ py::convert(param1) };
                    if (!out1)
                    {
                        return nullptr;
                    }
                    return PyTuple_Pack(2, out0.get(), out1.get());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* get_Size() noexcept override
        {
            try
            {
                return py::convert(_obj.Size());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        PyObject* dunder_iter() noexcept override
        {
            try
            {
                return py::convert(_obj.First());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        Py_ssize_t map_length() noexcept override
        {
            try
            {
                return static_cast<Py_ssize_t>(_obj.Size());
            }
            catch (...)
            {
                py::to_PyErr();
                return -1;
            }
        }
        PyObject* map_subscript(PyObject* key) noexcept override
        {
            try
            {
                return py::convert(_obj.Lookup(py::convert_to<K>(key)));
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }

        winrt::Windows::Foundation::Collections::IMapView<K, V> _obj{ nullptr };
    };

    template<typename K, typename V>
    struct IMap : public py::proj::Windows::Foundation::Collections::IMap
    {
        IMap(winrt::Windows::Foundation::Collections::IMap<K, V> o) : _obj(o) {}
        winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept override { return _obj; }
        std::size_t hash() noexcept override { return py::get_instance_hash(_obj); }
        PyObject* Clear(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    _obj.Clear();
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* First(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    return py::convert(_obj.First());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* GetView(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    return py::convert(_obj.GetView());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* HasKey(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<K>(args, 0);

                    return py::convert(_obj.HasKey(param0));
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* Insert(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 2)
            {
                try
                {
                    auto param0 = py::convert_to<K>(args, 0);
                    auto param1 = py::convert_to<V>(args, 1);

                    return py::convert(_obj.Insert(param0, param1));
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* Lookup(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<K>(args, 0);

                    return py::convert(_obj.Lookup(param0));
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* Remove(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<K>(args, 0);

                    _obj.Remove(param0);
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* get_Size() noexcept override
        {
            try
            {
                return py::convert(_obj.Size());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        PyObject* dunder_iter() noexcept override
        {
            try
            {
                return py::convert(_obj.First());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        Py_ssize_t map_length() noexcept override
        {
            try
            {
                return static_cast<Py_ssize_t>(_obj.Size());
            }
            catch (...)
            {
                py::to_PyErr();
                return -1;
            }
        }
        PyObject* map_subscript(PyObject* key) noexcept override
        {
            try
            {
                return py::convert(_obj.Lookup(py::convert_to<K>(key)));
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        int map_assign(PyObject* key, PyObject* value) noexcept override
        {
            try
            {
                auto _key = py::convert_to<K>(key);
                if (value == nullptr) { _obj.Remove(_key); }
                else { _obj.Insert(_key, py::convert_to<V>(value)); }
                return 0;
            }
            catch (...)
            {
                py::to_PyErr();
                return -1;
            }
        }

        winrt::Windows::Foundation::Collections::IMap<K, V> _obj{ nullptr };
    };

    template<typename K, typename V>
    struct IObservableMap : public py::proj::Windows::Foundation::Collections::IObservableMap
    {
        IObservableMap(winrt::Windows::Foundation::Collections::IObservableMap<K, V> o) : _obj(o) {}
        winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept override { return _obj; }
        std::size_t hash() noexcept override { return py::get_instance_hash(_obj); }
        PyObject* Clear(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    _obj.Clear();
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* First(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    return py::convert(_obj.First());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* GetView(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    return py::convert(_obj.GetView());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* HasKey(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<K>(args, 0);

                    return py::convert(_obj.HasKey(param0));
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* Insert(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 2)
            {
                try
                {
                    auto param0 = py::convert_to<K>(args, 0);
                    auto param1 = py::convert_to<V>(args, 1);

                    return py::convert(_obj.Insert(param0, param1));
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* Lookup(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<K>(args, 0);

                    return py::convert(_obj.Lookup(param0));
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* Remove(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<K>(args, 0);

                    _obj.Remove(param0);
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* get_Size() noexcept override
        {
            try
            {
                return py::convert(_obj.Size());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        PyObject* add_MapChanged(PyObject* arg) noexcept override
        {
            try
            {
                auto param0 = py::convert_to<winrt::Windows::Foundation::Collections::MapChangedEventHandler<K, V>>(arg);

                return py::convert(_obj.MapChanged(param0));
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        PyObject* remove_MapChanged(PyObject* arg) noexcept override
        {
            try
            {
                auto param0 = py::convert_to<winrt::event_token>(arg);

                _obj.MapChanged(param0);
                Py_RETURN_NONE;
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        PyObject* dunder_iter() noexcept override
        {
            try
            {
                return py::convert(_obj.First());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        Py_ssize_t map_length() noexcept override
        {
            try
            {
                return static_cast<Py_ssize_t>(_obj.Size());
            }
            catch (...)
            {
                py::to_PyErr();
                return -1;
            }
        }
        PyObject* map_subscript(PyObject* key) noexcept override
        {
            try
            {
                return py::convert(_obj.Lookup(py::convert_to<K>(key)));
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        int map_assign(PyObject* key, PyObject* value) noexcept override
        {
            try
            {
                auto _key = py::convert_to<K>(key);
                if (value == nullptr) { _obj.Remove(_key); }
                else { _obj.Insert(_key, py::convert_to<V>(value)); }
                return 0;
            }
            catch (...)
            {
                py::to_PyErr();
                return -1;
            }
        }

        winrt::Windows::Foundation::Collections::IObservableMap<K, V> _obj{ nullptr };
    };

    template<typename T>
    struct IObservableVector : public py::proj::Windows::Foundation::Collections::IObservableVector
    {
        IObservableVector(winrt::Windows::Foundation::Collections::IObservableVector<T> o) : _obj(o) {}
        winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept override { return _obj; }
        std::size_t hash() noexcept override { return py::get_instance_hash(_obj); }
        PyObject* Append(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<T>(args, 0);

                    _obj.Append(param0);
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* Clear(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    _obj.Clear();
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* First(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    return py::convert(_obj.First());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* GetAt(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<uint32_t>(args, 0);

                    return py::convert(_obj.GetAt(param0));
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* GetMany(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 2)
            {
                try
                {
                    auto param0 = py::convert_to<uint32_t>(args, 0);
                    auto param1_count = py::convert_to<winrt::com_array<T>::size_type>(args, 1);
                    winrt::com_array<T> param1 ( param1_count, py::empty_instance<T>::get() );

                    auto return_value = _obj.GetMany(param0, param1);

                    py::pyobj_handle out_return_value{ py::convert(return_value) };
                    if (!out_return_value)
                    {
                        return nullptr;
                    }
                    py::pyobj_handle out1{ py::convert(param1) };
                    if (!out1)
                    {
                        return nullptr;
                    }
                    return PyTuple_Pack(2, out_return_value.get(), out1.get());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* GetView(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    return py::convert(_obj.GetView());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* IndexOf(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<T>(args, 0);
                    uint32_t param1 {  };

                    auto return_value = _obj.IndexOf(param0, param1);

                    py::pyobj_handle out_return_value{ py::convert(return_value) };
                    if (!out_return_value)
                    {
                        return nullptr;
                    }
                    py::pyobj_handle out1{ py::convert(param1) };
                    if (!out1)
                    {
                        return nullptr;
                    }
                    return PyTuple_Pack(2, out_return_value.get(), out1.get());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* InsertAt(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 2)
            {
                try
                {
                    auto param0 = py::convert_to<uint32_t>(args, 0);
                    auto param1 = py::convert_to<T>(args, 1);

                    _obj.InsertAt(param0, param1);
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* RemoveAt(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<uint32_t>(args, 0);

                    _obj.RemoveAt(param0);
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* RemoveAtEnd(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    _obj.RemoveAtEnd();
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* ReplaceAll(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto _param0 = py::convert_to<winrt::com_array<T>>(args, 0);
                    auto param0 = winrt::array_view<const T>(_param0.data(), _param0.data() + _param0.size());

                    _obj.ReplaceAll(param0);
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* SetAt(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 2)
            {
                try
                {
                    auto param0 = py::convert_to<uint32_t>(args, 0);
                    auto param1 = py::convert_to<T>(args, 1);

                    _obj.SetAt(param0, param1);
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* get_Size() noexcept override
        {
            try
            {
                return py::convert(_obj.Size());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        PyObject* add_VectorChanged(PyObject* arg) noexcept override
        {
            try
            {
                auto param0 = py::convert_to<winrt::Windows::Foundation::Collections::VectorChangedEventHandler<T>>(arg);

                return py::convert(_obj.VectorChanged(param0));
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        PyObject* remove_VectorChanged(PyObject* arg) noexcept override
        {
            try
            {
                auto param0 = py::convert_to<winrt::event_token>(arg);

                _obj.VectorChanged(param0);
                Py_RETURN_NONE;
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        PyObject* dunder_iter() noexcept override
        {
            try
            {
                return py::convert(_obj.First());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        Py_ssize_t seq_length() noexcept override
        {
            try
            {
                return static_cast<Py_ssize_t>(_obj.Size());
            }
            catch (...)
            {
                py::to_PyErr();
                return -1;
            }
        }
        PyObject* seq_item(Py_ssize_t i) noexcept override
        {
            try
            {
                return py::convert(_obj.GetAt(static_cast<uint32_t>(i)));
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        int seq_assign(Py_ssize_t i, PyObject* value) noexcept override
        {
            try
            {
                if (value == nullptr) { _obj.RemoveAt(static_cast<uint32_t>(i)); }
                else { _obj.SetAt(static_cast<uint32_t>(i), py::convert_to<T>(value)); }
                return 0;
            }
            catch (...)
            {
                py::to_PyErr();
                return -1;
            }
        }

        winrt::Windows::Foundation::Collections::IObservableVector<T> _obj{ nullptr };
    };

    template<typename T>
    struct IVectorView : public py::proj::Windows::Foundation::Collections::IVectorView
    {
        IVectorView(winrt::Windows::Foundation::Collections::IVectorView<T> o) : _obj(o) {}
        winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept override { return _obj; }
        std::size_t hash() noexcept override { return py::get_instance_hash(_obj); }
        PyObject* First(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    return py::convert(_obj.First());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* GetAt(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<uint32_t>(args, 0);

                    return py::convert(_obj.GetAt(param0));
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* GetMany(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 2)
            {
                try
                {
                    auto param0 = py::convert_to<uint32_t>(args, 0);
                    auto param1_count = py::convert_to<winrt::com_array<T>::size_type>(args, 1);
                    winrt::com_array<T> param1 ( param1_count, py::empty_instance<T>::get() );

                    auto return_value = _obj.GetMany(param0, param1);

                    py::pyobj_handle out_return_value{ py::convert(return_value) };
                    if (!out_return_value)
                    {
                        return nullptr;
                    }
                    py::pyobj_handle out1{ py::convert(param1) };
                    if (!out1)
                    {
                        return nullptr;
                    }
                    return PyTuple_Pack(2, out_return_value.get(), out1.get());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* IndexOf(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<T>(args, 0);
                    uint32_t param1 {  };

                    auto return_value = _obj.IndexOf(param0, param1);

                    py::pyobj_handle out_return_value{ py::convert(return_value) };
                    if (!out_return_value)
                    {
                        return nullptr;
                    }
                    py::pyobj_handle out1{ py::convert(param1) };
                    if (!out1)
                    {
                        return nullptr;
                    }
                    return PyTuple_Pack(2, out_return_value.get(), out1.get());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* get_Size() noexcept override
        {
            try
            {
                return py::convert(_obj.Size());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        PyObject* dunder_iter() noexcept override
        {
            try
            {
                return py::convert(_obj.First());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        Py_ssize_t seq_length() noexcept override
        {
            try
            {
                return static_cast<Py_ssize_t>(_obj.Size());
            }
            catch (...)
            {
                py::to_PyErr();
                return -1;
            }
        }
        PyObject* seq_item(Py_ssize_t i) noexcept override
        {
            try
            {
                return py::convert(_obj.GetAt(static_cast<uint32_t>(i)));
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }

        winrt::Windows::Foundation::Collections::IVectorView<T> _obj{ nullptr };
    };

    template<typename T>
    struct IVector : public py::proj::Windows::Foundation::Collections::IVector
    {
        IVector(winrt::Windows::Foundation::Collections::IVector<T> o) : _obj(o) {}
        winrt::Windows::Foundation::IUnknown const& get_unknown() noexcept override { return _obj; }
        std::size_t hash() noexcept override { return py::get_instance_hash(_obj); }
        PyObject* Append(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<T>(args, 0);

                    _obj.Append(param0);
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* Clear(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    _obj.Clear();
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* First(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    return py::convert(_obj.First());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* GetAt(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<uint32_t>(args, 0);

                    return py::convert(_obj.GetAt(param0));
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* GetMany(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 2)
            {
                try
                {
                    auto param0 = py::convert_to<uint32_t>(args, 0);
                    auto param1_count = py::convert_to<winrt::com_array<T>::size_type>(args, 1);
                    winrt::com_array<T> param1 ( param1_count, py::empty_instance<T>::get() );

                    auto return_value = _obj.GetMany(param0, param1);

                    py::pyobj_handle out_return_value{ py::convert(return_value) };
                    if (!out_return_value)
                    {
                        return nullptr;
                    }
                    py::pyobj_handle out1{ py::convert(param1) };
                    if (!out1)
                    {
                        return nullptr;
                    }
                    return PyTuple_Pack(2, out_return_value.get(), out1.get());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* GetView(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    return py::convert(_obj.GetView());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* IndexOf(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<T>(args, 0);
                    uint32_t param1 {  };

                    auto return_value = _obj.IndexOf(param0, param1);

                    py::pyobj_handle out_return_value{ py::convert(return_value) };
                    if (!out_return_value)
                    {
                        return nullptr;
                    }
                    py::pyobj_handle out1{ py::convert(param1) };
                    if (!out1)
                    {
                        return nullptr;
                    }
                    return PyTuple_Pack(2, out_return_value.get(), out1.get());
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* InsertAt(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 2)
            {
                try
                {
                    auto param0 = py::convert_to<uint32_t>(args, 0);
                    auto param1 = py::convert_to<T>(args, 1);

                    _obj.InsertAt(param0, param1);
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* RemoveAt(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto param0 = py::convert_to<uint32_t>(args, 0);

                    _obj.RemoveAt(param0);
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* RemoveAtEnd(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 0)
            {
                try
                {
                    _obj.RemoveAtEnd();
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* ReplaceAll(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 1)
            {
                try
                {
                    auto _param0 = py::convert_to<winrt::com_array<T>>(args, 0);
                    auto param0 = winrt::array_view<const T>(_param0.data(), _param0.data() + _param0.size());

                    _obj.ReplaceAll(param0);
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* SetAt(PyObject* args) noexcept override
        {
            Py_ssize_t arg_count = PyTuple_Size(args);

            if (arg_count == 2)
            {
                try
                {
                    auto param0 = py::convert_to<uint32_t>(args, 0);
                    auto param1 = py::convert_to<T>(args, 1);

                    _obj.SetAt(param0, param1);
                    Py_RETURN_NONE;
                }
                catch (...)
                {
                    py::to_PyErr();
                    return nullptr;
                }
            }
            else
            {
                py::set_invalid_arg_count_error(arg_count);
                return nullptr;
            }
        }
        PyObject* get_Size() noexcept override
        {
            try
            {
                return py::convert(_obj.Size());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        PyObject* dunder_iter() noexcept override
        {
            try
            {
                return py::convert(_obj.First());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        Py_ssize_t seq_length() noexcept override
        {
            try
            {
                return static_cast<Py_ssize_t>(_obj.Size());
            }
            catch (...)
            {
                py::to_PyErr();
                return -1;
            }
        }
        PyObject* seq_item(Py_ssize_t i) noexcept override
        {
            try
            {
                return py::convert(_obj.GetAt(static_cast<uint32_t>(i)));
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        int seq_assign(Py_ssize_t i, PyObject* value) noexcept override
        {
            try
            {
                if (value == nullptr) { _obj.RemoveAt(static_cast<uint32_t>(i)); }
                else { _obj.SetAt(static_cast<uint32_t>(i), py::convert_to<T>(value)); }
                return 0;
            }
            catch (...)
            {
                py::to_PyErr();
                return -1;
            }
        }

        winrt::Windows::Foundation::Collections::IVector<T> _obj{ nullptr };
    };
}

namespace py::wrapper::Windows::Foundation::Collections
{
    using PropertySet = py::winrt_wrapper<winrt::Windows::Foundation::Collections::PropertySet>;
    using StringMap = py::winrt_wrapper<winrt::Windows::Foundation::Collections::StringMap>;
    using ValueSet = py::winrt_wrapper<winrt::Windows::Foundation::Collections::ValueSet>;
    using IIterable = py::winrt_pinterface_wrapper<py::proj::Windows::Foundation::Collections::IIterable>;
    using IIterator = py::winrt_pinterface_wrapper<py::proj::Windows::Foundation::Collections::IIterator>;
    using IKeyValuePair = py::winrt_pinterface_wrapper<py::proj::Windows::Foundation::Collections::IKeyValuePair>;
    using IMapChangedEventArgs = py::winrt_pinterface_wrapper<py::proj::Windows::Foundation::Collections::IMapChangedEventArgs>;
    using IMapView = py::winrt_pinterface_wrapper<py::proj::Windows::Foundation::Collections::IMapView>;
    using IMap = py::winrt_pinterface_wrapper<py::proj::Windows::Foundation::Collections::IMap>;
    using IObservableMap = py::winrt_pinterface_wrapper<py::proj::Windows::Foundation::Collections::IObservableMap>;
    using IObservableVector = py::winrt_pinterface_wrapper<py::proj::Windows::Foundation::Collections::IObservableVector>;
    using IPropertySet = py::winrt_wrapper<winrt::Windows::Foundation::Collections::IPropertySet>;
    using IVectorChangedEventArgs = py::winrt_wrapper<winrt::Windows::Foundation::Collections::IVectorChangedEventArgs>;
    using IVectorView = py::winrt_pinterface_wrapper<py::proj::Windows::Foundation::Collections::IVectorView>;
    using IVector = py::winrt_pinterface_wrapper<py::proj::Windows::Foundation::Collections::IVector>;
}

namespace py
{
    template<>
    struct winrt_type<winrt::Windows::Foundation::Collections::PropertySet>
    {
        static PyTypeObject* python_type;
        static PyTypeObject* get_python_type() { return python_type; }
    };

    template<>
    struct winrt_type<winrt::Windows::Foundation::Collections::StringMap>
    {
        static PyTypeObject* python_type;
        static PyTypeObject* get_python_type() { return python_type; }
    };

    template<>
    struct winrt_type<winrt::Windows::Foundation::Collections::ValueSet>
    {
        static PyTypeObject* python_type;
        static PyTypeObject* get_python_type() { return python_type; }
    };

    template<>
    struct winrt_type<py::proj::Windows::Foundation::Collections::IIterable>
    {
        static PyTypeObject* python_type;
        static PyTypeObject* get_python_type() { return python_type; }
    };

    template<>
    struct winrt_type<py::proj::Windows::Foundation::Collections::IIterator>
    {
        static PyTypeObject* python_type;
        static PyTypeObject* get_python_type() { return python_type; }
    };

    template<>
    struct winrt_type<py::proj::Windows::Foundation::Collections::IKeyValuePair>
    {
        static PyTypeObject* python_type;
        static PyTypeObject* get_python_type() { return python_type; }
    };

    template<>
    struct winrt_type<py::proj::Windows::Foundation::Collections::IMapChangedEventArgs>
    {
        static PyTypeObject* python_type;
        static PyTypeObject* get_python_type() { return python_type; }
    };

    template<>
    struct winrt_type<py::proj::Windows::Foundation::Collections::IMapView>
    {
        static PyTypeObject* python_type;
        static PyTypeObject* get_python_type() { return python_type; }
    };

    template<>
    struct winrt_type<py::proj::Windows::Foundation::Collections::IMap>
    {
        static PyTypeObject* python_type;
        static PyTypeObject* get_python_type() { return python_type; }
    };

    template<>
    struct winrt_type<py::proj::Windows::Foundation::Collections::IObservableMap>
    {
        static PyTypeObject* python_type;
        static PyTypeObject* get_python_type() { return python_type; }
    };

    template<>
    struct winrt_type<py::proj::Windows::Foundation::Collections::IObservableVector>
    {
        static PyTypeObject* python_type;
        static PyTypeObject* get_python_type() { return python_type; }
    };

    template<>
    struct winrt_type<winrt::Windows::Foundation::Collections::IPropertySet>
    {
        static PyTypeObject* python_type;
        static PyTypeObject* get_python_type() { return python_type; }
    };

    template<>
    struct winrt_type<winrt::Windows::Foundation::Collections::IVectorChangedEventArgs>
    {
        static PyTypeObject* python_type;
        static PyTypeObject* get_python_type() { return python_type; }
    };

    template<>
    struct winrt_type<py::proj::Windows::Foundation::Collections::IVectorView>
    {
        static PyTypeObject* python_type;
        static PyTypeObject* get_python_type() { return python_type; }
    };

    template<>
    struct winrt_type<py::proj::Windows::Foundation::Collections::IVector>
    {
        static PyTypeObject* python_type;
        static PyTypeObject* get_python_type() { return python_type; }
    };

    template <typename T>
    struct pinterface_python_type<winrt::Windows::Foundation::Collections::IIterable<T>>
    {
        using abstract = py::proj::Windows::Foundation::Collections::IIterable;
        using concrete = py::impl::Windows::Foundation::Collections::IIterable<T>;
    };

    template <typename T>
    struct pinterface_python_type<winrt::Windows::Foundation::Collections::IIterator<T>>
    {
        using abstract = py::proj::Windows::Foundation::Collections::IIterator;
        using concrete = py::impl::Windows::Foundation::Collections::IIterator<T>;
    };

    template <typename K, typename V>
    struct pinterface_python_type<winrt::Windows::Foundation::Collections::IKeyValuePair<K, V>>
    {
        using abstract = py::proj::Windows::Foundation::Collections::IKeyValuePair;
        using concrete = py::impl::Windows::Foundation::Collections::IKeyValuePair<K, V>;
    };

    template <typename K>
    struct pinterface_python_type<winrt::Windows::Foundation::Collections::IMapChangedEventArgs<K>>
    {
        using abstract = py::proj::Windows::Foundation::Collections::IMapChangedEventArgs;
        using concrete = py::impl::Windows::Foundation::Collections::IMapChangedEventArgs<K>;
    };

    template <typename K, typename V>
    struct pinterface_python_type<winrt::Windows::Foundation::Collections::IMapView<K, V>>
    {
        using abstract = py::proj::Windows::Foundation::Collections::IMapView;
        using concrete = py::impl::Windows::Foundation::Collections::IMapView<K, V>;
    };

    template <typename K, typename V>
    struct pinterface_python_type<winrt::Windows::Foundation::Collections::IMap<K, V>>
    {
        using abstract = py::proj::Windows::Foundation::Collections::IMap;
        using concrete = py::impl::Windows::Foundation::Collections::IMap<K, V>;
    };

    template <typename K, typename V>
    struct pinterface_python_type<winrt::Windows::Foundation::Collections::IObservableMap<K, V>>
    {
        using abstract = py::proj::Windows::Foundation::Collections::IObservableMap;
        using concrete = py::impl::Windows::Foundation::Collections::IObservableMap<K, V>;
    };

    template <typename T>
    struct pinterface_python_type<winrt::Windows::Foundation::Collections::IObservableVector<T>>
    {
        using abstract = py::proj::Windows::Foundation::Collections::IObservableVector;
        using concrete = py::impl::Windows::Foundation::Collections::IObservableVector<T>;
    };

    template <typename T>
    struct pinterface_python_type<winrt::Windows::Foundation::Collections::IVectorView<T>>
    {
        using abstract = py::proj::Windows::Foundation::Collections::IVectorView;
        using concrete = py::impl::Windows::Foundation::Collections::IVectorView<T>;
    };

    template <typename T>
    struct pinterface_python_type<winrt::Windows::Foundation::Collections::IVector<T>>
    {
        using abstract = py::proj::Windows::Foundation::Collections::IVector;
        using concrete = py::impl::Windows::Foundation::Collections::IVector<T>;
    };

    template <typename K, typename V>
    struct delegate_python_type<winrt::Windows::Foundation::Collections::MapChangedEventHandler<K, V>>
    {
        using type = py::impl::Windows::Foundation::Collections::MapChangedEventHandler<K, V>;
    };

    template <typename T>
    struct delegate_python_type<winrt::Windows::Foundation::Collections::VectorChangedEventHandler<T>>
    {
        using type = py::impl::Windows::Foundation::Collections::VectorChangedEventHandler<T>;
    };

}
