// Copyright David Abrahams 2001.
// Distributed under 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)

#include <boost/python/detail/prefix.hpp>
#include <boost/mpl/lambda.hpp> // #including this first is an intel6 workaround

#include <boost/python/object/class.hpp>
#include <boost/python/object/instance.hpp>
#include <boost/python/object/class_detail.hpp>
#include <boost/python/scope.hpp>
#include <boost/python/converter/registry.hpp>
#include <boost/python/object/find_instance.hpp>
#include <boost/python/object/pickle_support.hpp>
#include <boost/python/detail/map_entry.hpp>
#include <boost/python/object.hpp>
#include <boost/python/object_protocol.hpp>
#include <boost/detail/binary_search.hpp>
#include <boost/python/self.hpp>
#include <boost/python/dict.hpp>
#include <boost/python/str.hpp>
#include <boost/python/ssize_t.hpp>
#include <functional>
#include <vector>
#include <cstddef>
#include <new>
#include <structmember.h>

namespace boost { namespace python {

# ifdef BOOST_PYTHON_SELF_IS_CLASS
namespace self_ns
{
  self_t self;
}
# endif 

instance_holder::instance_holder()
    : m_next(0)
{
}

instance_holder::~instance_holder()
{
}

extern "C"
{
  // This is copied from typeobject.c in the Python sources. Even though
  // class_metatype_object doesn't set Py_TPFLAGS_HAVE_GC, that bit gets
  // filled in by the base class initialization process in
  // PyType_Ready(). However, tp_is_gc is *not* copied from the base
  // type, making it assume that classes are GC-able even if (like
  // class_type_object) they're statically allocated.
  static int
  type_is_gc(PyTypeObject *python_type)
  {
      return python_type->tp_flags & Py_TPFLAGS_HEAPTYPE;
  }

  // This is also copied from the Python sources.  We can't implement
  // static_data as a subclass property effectively without it.
  typedef struct {
      PyObject_HEAD
      PyObject *prop_get;
      PyObject *prop_set;
      PyObject *prop_del;
      PyObject *prop_doc;
      int getter_doc;
  } propertyobject;

  // Copied from Python source and removed the part for setting docstring,
  // since we don't have a setter for __doc__ and trying to set it will
  // cause the init fail.
  static int property_init(PyObject *self, PyObject *args, PyObject *kwds)
  {
      PyObject *get = NULL, *set = NULL, *del = NULL, *doc = NULL;
      static char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
      propertyobject *prop = (propertyobject *)self;

      if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property",
                  kwlist, &get, &set, &del, &doc))
          return -1;

      if (get == Py_None)
          get = NULL;
      if (set == Py_None)
          set = NULL;
      if (del == Py_None)
          del = NULL;

      Py_XINCREF(get);
      Py_XINCREF(set);
      Py_XINCREF(del);
      Py_XINCREF(doc);

      prop->prop_get = get;
      prop->prop_set = set;
      prop->prop_del = del;
      prop->prop_doc = doc;
      prop->getter_doc = 0;

      return 0;
  }

 
  static PyObject *
  static_data_descr_get(PyObject *self, PyObject * /*obj*/, PyObject * /*type*/)
  {
      propertyobject *gs = (propertyobject *)self;

      return PyObject_CallFunction(gs->prop_get, const_cast<char*>("()"));
  }

  static int
  static_data_descr_set(PyObject *self, PyObject * /*obj*/, PyObject *value)
  {
      propertyobject *gs = (propertyobject *)self;
      PyObject *func, *res;

      if (value == NULL)
          func = gs->prop_del;
      else
          func = gs->prop_set;
      if (func == NULL) {
          PyErr_SetString(PyExc_AttributeError,
                          value == NULL ?
                          "can't delete attribute" :
                          "can't set attribute");
          return -1;
      }
      if (value == NULL)
          res = PyObject_CallFunction(func, const_cast<char*>("()"));
      else
          res = PyObject_CallFunction(func, const_cast<char*>("(O)"), value);
      if (res == NULL)
          return -1;
      Py_DECREF(res);
      return 0;
  }
}

static PyTypeObject static_data_object = {
    PyVarObject_HEAD_INIT(NULL, 0)
    const_cast<char*>("Boost.Python.StaticProperty"),
    sizeof(propertyobject),
    0,
    0,                                      /* tp_dealloc */
    0,                                      /* tp_print */
    0,                                      /* tp_getattr */
    0,                                      /* tp_setattr */
    0,                                      /* tp_compare */
    0,                                      /* tp_repr */
    0,                                      /* tp_as_number */
    0,                                      /* tp_as_sequence */
    0,                                      /* tp_as_mapping */
    0,                                      /* tp_hash */
    0,                                      /* tp_call */
    0,                                      /* tp_str */
    0,                                      /* tp_getattro */
    0,                                      /* tp_setattro */
    0,                                      /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
    | Py_TPFLAGS_BASETYPE,          /* tp_flags */
    0,                                      /* tp_doc */
    0,                                      /* tp_traverse */
    0,                                      /* tp_clear */
    0,                                      /* tp_richcompare */
    0,                                      /* tp_weaklistoffset */
    0,                                      /* tp_iter */
    0,                                      /* tp_iternext */
    0,                                      /* tp_methods */
    0,                                      /* tp_members */
    0,                                      /* tp_getset */
    0, //&PyProperty_Type,                           /* tp_base */
    0,                                      /* tp_dict */
    static_data_descr_get,                                      /* tp_descr_get */
    static_data_descr_set,                                      /* tp_descr_set */
    0,                                      /* tp_dictoffset */
    property_init,                                      /* tp_init */
    0,                                      /* tp_alloc */
    0, // filled in with type_new           /* tp_new */
    0, // filled in with __PyObject_GC_Del  /* tp_free */
    0,                                      /* tp_is_gc */
    0,                                      /* tp_bases */
    0,                                      /* tp_mro */
    0,                                      /* tp_cache */
    0,                                      /* tp_subclasses */
    0,                                      /* tp_weaklist */
#if PYTHON_API_VERSION >= 1012
    0                                       /* tp_del */
#endif
};

namespace objects
{
#if PY_VERSION_HEX < 0x03000000
  // XXX Not sure why this run into compiling error in Python 3
  extern "C"
  {
      // This declaration needed due to broken Python 2.2 headers
      extern DL_IMPORT(PyTypeObject) PyProperty_Type;
  }
#endif

  BOOST_PYTHON_DECL PyObject* static_data()
  {
      if (static_data_object.tp_dict == 0)
      {
          Py_TYPE(&static_data_object) = &PyType_Type;
          static_data_object.tp_base = &PyProperty_Type;
          if (PyType_Ready(&static_data_object))
              return 0;
      }
      return upcast<PyObject>(&static_data_object);
  }
}  

extern "C"
{
    // Ordinarily, descriptors have a certain assymetry: you can use
    // them to read attributes off the class object they adorn, but
    // writing the same attribute on the class object always replaces
    // the descriptor in the class __dict__.  In order to properly
    // represent C++ static data members, we need to allow them to be
    // written through the class instance.  This function of the
    // metaclass makes it possible.
    static int
    class_setattro(PyObject *obj, PyObject *name, PyObject* value)
    {
        // Must use "private" Python implementation detail
        // _PyType_Lookup instead of PyObject_GetAttr because the
        // latter will always end up calling the descr_get function on
        // any descriptor it finds; we need the unadulterated
        // descriptor here.
        PyObject* a = _PyType_Lookup(downcast<PyTypeObject>(obj), name);

        // a is a borrowed reference or 0
        
        // If we found a static data descriptor, call it directly to
        // force it to set the static data member
        if (a != 0 && PyObject_IsInstance(a, objects::static_data()))
            return Py_TYPE(a)->tp_descr_set(a, obj, value);
        else
            return PyType_Type.tp_setattro(obj, name, value);
    }
}

static PyTypeObject class_metatype_object = {
    PyVarObject_HEAD_INIT(NULL, 0)
    const_cast<char*>("Boost.Python.class"),
    PyType_Type.tp_basicsize,
    0,
    0,                                      /* tp_dealloc */
    0,                                      /* tp_print */
    0,                                      /* tp_getattr */
    0,                                      /* tp_setattr */
    0,                                      /* tp_compare */
    0,                                      /* tp_repr */
    0,                                      /* tp_as_number */
    0,                                      /* tp_as_sequence */
    0,                                      /* tp_as_mapping */
    0,                                      /* tp_hash */
    0,                                      /* tp_call */
    0,                                      /* tp_str */
    0,                                      /* tp_getattro */
    class_setattro,                         /* tp_setattro */
    0,                                      /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
    | Py_TPFLAGS_BASETYPE,          /* tp_flags */
    0,                                      /* tp_doc */
    0,                                      /* tp_traverse */
    0,                                      /* tp_clear */
    0,                                      /* tp_richcompare */
    0,                                      /* tp_weaklistoffset */
    0,                                      /* tp_iter */
    0,                                      /* tp_iternext */
    0,                                      /* tp_methods */
    0,                                      /* tp_members */
    0,                                      /* tp_getset */
    0, //&PyType_Type,                           /* tp_base */
    0,                                      /* tp_dict */
    0,                                      /* tp_descr_get */
    0,                                      /* tp_descr_set */
    0,                                      /* tp_dictoffset */
    0,                                      /* tp_init */
    0,                                      /* tp_alloc */
    0, // filled in with type_new           /* tp_new */
    0, // filled in with __PyObject_GC_Del  /* tp_free */
    (inquiry)type_is_gc,                    /* tp_is_gc */
    0,                                      /* tp_bases */
    0,                                      /* tp_mro */
    0,                                      /* tp_cache */
    0,                                      /* tp_subclasses */
    0,                                      /* tp_weaklist */
#if PYTHON_API_VERSION >= 1012
    0                                       /* tp_del */
#endif
};

// Install the instance data for a C++ object into a Python instance
// object.
void instance_holder::install(PyObject* self) throw()
{
    assert(Py_TYPE(Py_TYPE(self)) == &class_metatype_object);
    m_next = ((objects::instance<>*)self)->objects;
    ((objects::instance<>*)self)->objects = this;
}


namespace objects
{
// Get the metatype object for all extension classes.
  BOOST_PYTHON_DECL type_handle class_metatype()
  {
      if (class_metatype_object.tp_dict == 0)
      {
          Py_TYPE(&class_metatype_object) = &PyType_Type;
          class_metatype_object.tp_base = &PyType_Type;
          if (PyType_Ready(&class_metatype_object))
              return type_handle();
      }
      return type_handle(borrowed(&class_metatype_object));
  }
  extern "C"
  {
      static void instance_dealloc(PyObject* inst)
      {
          instance<>* kill_me = (instance<>*)inst;

          for (instance_holder* p = kill_me->objects, *next; p != 0; p = next)
          {
              next = p->next();
              p->~instance_holder();
              instance_holder::deallocate(inst, dynamic_cast<void*>(p));
          }
        
          // Python 2.2.1 won't add weak references automatically when
          // tp_itemsize > 0, so we need to manage that
          // ourselves. Accordingly, we also have to clean up the
          // weakrefs ourselves.
          if (kill_me->weakrefs != NULL)
            PyObject_ClearWeakRefs(inst);

          Py_XDECREF(kill_me->dict);
          
          Py_TYPE(inst)->tp_free(inst);
      }

      static PyObject *
      instance_new(PyTypeObject* type_, PyObject* /*args*/, PyObject* /*kw*/)
      {
          // Attempt to find the __instance_size__ attribute. If not present, no problem.
          PyObject* d = type_->tp_dict;
          PyObject* instance_size_obj = PyObject_GetAttrString(d, const_cast<char*>("__instance_size__"));

          ssize_t instance_size = instance_size_obj ? 
#if PY_VERSION_HEX >= 0x03000000
              PyLong_AsSsize_t(instance_size_obj) : 0;
#else
              PyInt_AsLong(instance_size_obj) : 0;
#endif
          
          if (instance_size < 0)
              instance_size = 0;
          
          PyErr_Clear(); // Clear any errors that may have occurred.

          instance<>* result = (instance<>*)type_->tp_alloc(type_, instance_size);
          if (result)
          {
              // Guido says we can use ob_size for any purpose we
              // like, so we'll store the total size of the object
              // there. A negative number indicates that the extra
              // instance memory is not yet allocated to any holders.
#if PY_VERSION_HEX >= 0x02060000
              Py_SIZE(result) =
#else
              result->ob_size =
#endif
                  -(static_cast<int>(offsetof(instance<>,storage) + instance_size));
          }
          return (PyObject*)result;
      }

      static PyObject* instance_get_dict(PyObject* op, void*)
      {
          instance<>* inst = downcast<instance<> >(op);
          if (inst->dict == 0)
              inst->dict = PyDict_New();
          return python::xincref(inst->dict);
      }
    
      static int instance_set_dict(PyObject* op, PyObject* dict, void*)
      {
          instance<>* inst = downcast<instance<> >(op);
          python::xdecref(inst->dict);
          inst->dict = python::incref(dict);
          return 0;
      }

  }


  static PyGetSetDef instance_getsets[] = {
      {const_cast<char*>("__dict__"),  instance_get_dict,  instance_set_dict, NULL, 0},
      {0, 0, 0, 0, 0}
  };

  
  static PyMemberDef instance_members[] = {
      {const_cast<char*>("__weakref__"), T_OBJECT, offsetof(instance<>, weakrefs), 0, 0},
      {0, 0, 0, 0, 0}
  };

  static PyTypeObject class_type_object = {
      PyVarObject_HEAD_INIT(NULL, 0)
      const_cast<char*>("Boost.Python.instance"),
      offsetof(instance<>,storage),           /* tp_basicsize */
      1,                                      /* tp_itemsize */
      instance_dealloc,                       /* tp_dealloc */
      0,                                      /* tp_print */
      0,                                      /* tp_getattr */
      0,                                      /* tp_setattr */
      0,                                      /* tp_compare */
      0,                                      /* tp_repr */
      0,                                      /* tp_as_number */
      0,                                      /* tp_as_sequence */
      0,                                      /* tp_as_mapping */
      0,                                      /* tp_hash */
      0,                                      /* tp_call */
      0,                                      /* tp_str */
      0,                                      /* tp_getattro */
      0,                                      /* tp_setattro */
      0,                                      /* tp_as_buffer */
      Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
      | Py_TPFLAGS_BASETYPE,          /* tp_flags */
      0,                                      /* tp_doc */
      0,                                      /* tp_traverse */
      0,                                      /* tp_clear */
      0,                                      /* tp_richcompare */
      offsetof(instance<>,weakrefs),          /* tp_weaklistoffset */
      0,                                      /* tp_iter */
      0,                                      /* tp_iternext */
      0,                                      /* tp_methods */
      instance_members,                       /* tp_members */
      instance_getsets,                       /* tp_getset */
      0, //&PyBaseObject_Type,                /* tp_base */
      0,                                      /* tp_dict */
      0,                                      /* tp_descr_get */
      0,                                      /* tp_descr_set */
      offsetof(instance<>,dict),              /* tp_dictoffset */
      0,                                      /* tp_init */
      PyType_GenericAlloc,                    /* tp_alloc */
      instance_new,                           /* tp_new */
      0,                                      /* tp_free */
      0,                                      /* tp_is_gc */
      0,                                      /* tp_bases */
      0,                                      /* tp_mro */
      0,                                      /* tp_cache */
      0,                                      /* tp_subclasses */
      0,                                      /* tp_weaklist */
#if PYTHON_API_VERSION >= 1012
      0                                       /* tp_del */
#endif
  };

  BOOST_PYTHON_DECL type_handle class_type()
  {
      if (class_type_object.tp_dict == 0)
      {
          Py_TYPE(&class_type_object) = incref(class_metatype().get());
          class_type_object.tp_base = &PyBaseObject_Type;
          if (PyType_Ready(&class_type_object))
              return type_handle();
//          class_type_object.tp_setattro = class_setattro;
      }
      return type_handle(borrowed(&class_type_object));
  }

  BOOST_PYTHON_DECL void*
  find_instance_impl(PyObject* inst, type_info type, bool null_shared_ptr_only)
  {
      if (Py_TYPE(Py_TYPE(inst)) != &class_metatype_object)
          return 0;
    
      instance<>* self = reinterpret_cast<instance<>*>(inst);

      for (instance_holder* match = self->objects; match != 0; match = match->next())
      {
          void* const found = match->holds(type, null_shared_ptr_only);
          if (found)
              return found;
      }
      return 0;
  }

  object module_prefix()
  {
      return object(
          PyObject_IsInstance(scope().ptr(), upcast<PyObject>(&PyModule_Type))
          ? object(scope().attr("__name__"))
          : api::getattr(scope(), "__module__", str())
          );
  }

  namespace
  {
    // Find a registered class object corresponding to id. Return a
    // null handle if no such class is registered.
    inline type_handle query_class(type_info id)
    {
        converter::registration const* p = converter::registry::query(id);
        return type_handle(
            python::borrowed(
                python::allow_null(p ? p->m_class_object : 0))
            );
    }

    // Find a registered class corresponding to id. If not found,
    // throw an appropriate exception.
    type_handle get_class(type_info id)
    {
        type_handle result(query_class(id));

        if (result.get() == 0)
        {
            object report("extension class wrapper for base class ");
            report = report + id.name() + " has not been created yet";
            PyErr_SetObject(PyExc_RuntimeError, report.ptr());
            throw_error_already_set();
        }
        return result;
    }

    // class_base constructor
    //
    // name -      the name of the new Python class
    //
    // num_types - one more than the number of declared bases
    //
    // types -     array of python::type_info, the first item
    //             corresponding to the class being created, and the
    //             rest corresponding to its declared bases.
    //
    inline object
    new_class(char const* name, std::size_t num_types, type_info const* const types, char const* doc)
    {
      assert(num_types >= 1);
      
      // Build a tuple of the base Python type objects. If no bases
      // were declared, we'll use our class_type() as the single base
      // class.
      ssize_t const num_bases = (std::max)(num_types - 1, static_cast<std::size_t>(1));
      handle<> bases(PyTuple_New(num_bases));

      for (ssize_t i = 1; i <= num_bases; ++i)
      {
          type_handle c = (i >= static_cast<ssize_t>(num_types)) ? class_type() : get_class(types[i]);
          // PyTuple_SET_ITEM steals this reference
          PyTuple_SET_ITEM(bases.get(), static_cast<ssize_t>(i - 1), upcast<PyObject>(c.release()));
      }

      // Call the class metatype to create a new class
      dict d;
   
      object m = module_prefix();
      if (m) d["__module__"] = m;

      if (doc != 0)
          d["__doc__"] = doc;
      
      object result = object(class_metatype())(name, bases, d);
      assert(PyType_IsSubtype(Py_TYPE(result.ptr()), &PyType_Type));
      
      if (scope().ptr() != Py_None)
          scope().attr(name) = result;

      // For pickle. Will lead to informative error messages if pickling
      // is not enabled.
      result.attr("__reduce__") = object(make_instance_reduce_function());

      return result;
    }
  }
  
  class_base::class_base(
      char const* name, std::size_t num_types, type_info const* const types, char const* doc)
      : object(new_class(name, num_types, types, doc))
  {
      // Insert the new class object in the registry
      converter::registration& converters = const_cast<converter::registration&>(
          converter::registry::lookup(types[0]));

      // Class object is leaked, for now
      converters.m_class_object = (PyTypeObject*)incref(this->ptr());
  }

  BOOST_PYTHON_DECL void copy_class_object(type_info const& src, type_info const& dst)
  {
      converter::registration& dst_converters
          = const_cast<converter::registration&>(converter::registry::lookup(dst));
      
      converter::registration const& src_converters = converter::registry::lookup(src);

      dst_converters.m_class_object = src_converters.m_class_object;
  }
  
  void class_base::set_instance_size(std::size_t instance_size)
  {
      this->attr("__instance_size__") = instance_size;
  }
  
  void class_base::add_property(
    char const* name, object const& fget, char const* docstr)
  {
      object property(
          (python::detail::new_reference)
          PyObject_CallFunction((PyObject*)&PyProperty_Type, const_cast<char*>("Osss"), fget.ptr(), 0, 0, docstr));
      
      this->setattr(name, property);
  }

  void class_base::add_property(
    char const* name, object const& fget, object const& fset, char const* docstr)
  {
      object property(
          (python::detail::new_reference)
          PyObject_CallFunction((PyObject*)&PyProperty_Type, const_cast<char*>("OOss"), fget.ptr(), fset.ptr(), 0, docstr));
      
      this->setattr(name, property);
  }

  void class_base::add_static_property(char const* name, object const& fget)
  {
      object property(
          (python::detail::new_reference) 
          PyObject_CallFunction(static_data(), const_cast<char*>("O"), fget.ptr())
          );
      
      this->setattr(name, property);
  }

  void class_base::add_static_property(char const* name, object const& fget, object const& fset)
  {
      object property(
          (python::detail::new_reference)
          PyObject_CallFunction(static_data(), const_cast<char*>("OO"), fget.ptr(), fset.ptr()));
      
      this->setattr(name, property);
  }

  void class_base::setattr(char const* name, object const& x)
  {
      if (PyObject_SetAttrString(this->ptr(), const_cast<char*>(name), x.ptr()) < 0)
          throw_error_already_set();
  }

  namespace
  {
    extern "C" PyObject* no_init(PyObject*, PyObject*)
    {
        ::PyErr_SetString(::PyExc_RuntimeError, const_cast<char*>("This class cannot be instantiated from Python"));
        return NULL;
    }
    static ::PyMethodDef no_init_def = {
        const_cast<char*>("__init__"), no_init, METH_VARARGS,
        const_cast<char*>("Raises an exception\n"
                          "This class cannot be instantiated from Python\n")
    };
  }
  
  void class_base::def_no_init()
  {
      handle<> f(::PyCFunction_New(&no_init_def, 0));
      this->setattr("__init__", object(f));
  }

  void class_base::enable_pickling_(bool getstate_manages_dict)
  {
      setattr("__safe_for_unpickling__", object(true));
      
      if (getstate_manages_dict)
      {
          setattr("__getstate_manages_dict__", object(true));
      }
  }

  namespace
  {
    PyObject* callable_check(PyObject* callable)
    {
        if (PyCallable_Check(expect_non_null(callable)))
            return callable;

        ::PyErr_Format(
            PyExc_TypeError
          , const_cast<char*>("staticmethod expects callable object; got an object of type %s, which is not callable")
            , Py_TYPE(callable)->tp_name
            );
        
        throw_error_already_set();
        return 0;
    }
  }
  
  void class_base::make_method_static(const char * method_name)
  {
      PyTypeObject* self = downcast<PyTypeObject>(this->ptr());
      dict d((handle<>(borrowed(self->tp_dict))));

      object method(d[method_name]);

      this->attr(method_name) = object(
          handle<>(
              PyStaticMethod_New((callable_check)(method.ptr()) )
              ));
  }

  BOOST_PYTHON_DECL type_handle registered_class_object(type_info id)
  {
      return query_class(id);
  }
} // namespace objects


void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size)
{
    assert(Py_TYPE(Py_TYPE(self_)) == &class_metatype_object);
    objects::instance<>* self = (objects::instance<>*)self_;
    
    int total_size_needed = holder_offset + holder_size;
    
    if (-Py_SIZE(self) >= total_size_needed)
    {
        // holder_offset should at least point into the variable-sized part
        assert(holder_offset >= offsetof(objects::instance<>,storage));

        // Record the fact that the storage is occupied, noting where it starts
        Py_SIZE(self) = holder_offset;
        return (char*)self + holder_offset;
    }
    else
    {
        void* const result = PyMem_Malloc(holder_size);
        if (result == 0)
            throw std::bad_alloc();
        return result;
    }
}

void instance_holder::deallocate(PyObject* self_, void* storage) throw()
{
    assert(Py_TYPE(Py_TYPE(self_)) == &class_metatype_object);
    objects::instance<>* self = (objects::instance<>*)self_;
    if (storage != (char*)self + Py_SIZE(self))
    {
        PyMem_Free(storage);
    }
}

}} // namespace boost::python
