//=========================================================================
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt for details.
//
//  This software is distributed WITHOUT ANY WARRANTY; without even
//  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
//  PURPOSE.  See the above copyright notice for more information.
//=========================================================================

#include <utility>
#include <pybind11/pybind11.h>

namespace py = pybind11;

template <typename T, typename... Args>
using PySharedPtrClass = py::class_<T, std::shared_ptr<T>, Args... >;

#include "PybindArrangement.h"
#include "PybindArrangementHelper.h"
#include "PybindArrangementKind.h"
#include "PybindAttributeAssignments.h"
#include "PybindAttributeListPhrase.h"
#include "PybindCellEntity.h"
#include "PybindChain.h"
#include "PybindDefaultSession.h"
#include "PybindDescriptivePhrase.h"
#include "PybindEdge.h"
#include "PybindEdgeUse.h"
#include "PybindEntity.h"
#include "PybindEntityIterator.h"
#include "PybindEntityListPhrase.h"
#include "PybindEntityPhrase.h"
#include "PybindEntityRef.h"
#include "PybindEntityRefArrangementOps.h"
#include "PybindEntityTypeBits.h"
#include "PybindEntityTypeSubphrases.h"
#include "PybindEvents.h"
#include "PybindFace.h"
#include "PybindFaceUse.h"
#include "PybindGridInfo.h"
#include "PybindGroup.h"
#include "PybindInstance.h"
#include "PybindLoop.h"
#include "PybindManager.h"
#include "PybindMeshListPhrase.h"
#include "PybindMeshPhrase.h"
#include "PybindModel.h"
#include "PybindOperator.h"
#include "PybindPropertyListPhrase.h"
#include "PybindPropertyValuePhrase.h"
#include "PybindRemoteOperator.h"
#include "PybindSession.h"
#include "PybindSessionIO.h"
#include "PybindSessionIOJSON.h"
#include "PybindSessionRef.h"
#include "PybindSessionRegistrar.h"
#include "PybindShell.h"
#include "PybindShellEntity.h"
#include "PybindSimpleModelSubphrases.h"
#include "PybindSubphraseGenerator.h"
#include "PybindTessellation.h"
#include "PybindUseEntity.h"
#include "PybindVertex.h"
#include "PybindVertexUse.h"
#include "PybindVolume.h"
#include "PybindVolumeUse.h"

PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>);

PYBIND11_PLUGIN(smtkPybindModel)
{
  py::module model("smtkPybindModel", "<description>");

  // The order of these function calls is important! It was determined by
  // comparing the dependencies of each of the wrapped objects.
  pybind11_init_smtk_model_Orientation(model);
  pybind11_init_smtk_model_ArrangementKind(model);
  pybind11_init_smtk_model_ManagerEventChangeType(model);
  pybind11_init_smtk_model_ManagerEventRelationType(model);
  pybind11_init_smtk_model_OperatorEventType(model);
  py::class_< smtk::model::Arrangement > smtk_model_Arrangement = pybind11_init_smtk_model_Arrangement(model);
  py::class_< smtk::model::ArrangementHelper > smtk_model_ArrangementHelper = pybind11_init_smtk_model_ArrangementHelper(model);
  py::class_< smtk::model::ArrangementReference > smtk_model_ArrangementReference = pybind11_init_smtk_model_ArrangementReference(model);
  py::class_< smtk::model::AttributeAssignments > smtk_model_AttributeAssignments = pybind11_init_smtk_model_AttributeAssignments(model);
  PySharedPtrClass< smtk::model::DescriptivePhrase > smtk_model_DescriptivePhrase = pybind11_init_smtk_model_DescriptivePhrase(model);
  py::class_< smtk::model::Entity > smtk_model_Entity = pybind11_init_smtk_model_Entity(model);
  py::class_< smtk::model::EntityIterator > smtk_model_EntityIterator = pybind11_init_smtk_model_EntityIterator(model);
  py::class_< smtk::model::EntityRef > smtk_model_EntityRef = pybind11_init_smtk_model_EntityRef(model);
  py::class_< smtk::model::EntityRefArrangementOps > smtk_model_EntityRefArrangementOps = pybind11_init_smtk_model_EntityRefArrangementOps(model);
  py::class_< smtk::model::GridInfo > smtk_model_GridInfo = pybind11_init_smtk_model_GridInfo(model);
  PySharedPtrClass< smtk::model::Manager > smtk_model_Manager = pybind11_init_smtk_model_Manager(model);
  PySharedPtrClass< smtk::model::Operator > smtk_model_Operator = pybind11_init_smtk_model_Operator(model);
  PySharedPtrClass< smtk::model::Session > smtk_model_Session = pybind11_init_smtk_model_Session(model);
  py::class_< smtk::model::SessionIO > smtk_model_SessionIO = pybind11_init_smtk_model_SessionIO(model);
  py::class_< smtk::model::SessionRegistrar > smtk_model_SessionRegistrar = pybind11_init_smtk_model_SessionRegistrar(model);
  py::class_< smtk::model::StaticSessionInfo > smtk_model_StaticSessionInfo = pybind11_init_smtk_model_StaticSessionInfo(model);
  PySharedPtrClass< smtk::model::SubphraseGenerator > smtk_model_SubphraseGenerator = pybind11_init_smtk_model_SubphraseGenerator(model);
  py::class_< smtk::model::Tessellation > smtk_model_Tessellation = pybind11_init_smtk_model_Tessellation(model);
  pybind11_init_smtk_model_EntityTypeBits(model);
  pybind11_init_smtk_model_AbbreviationForArrangementKind(model);
  pybind11_init_smtk_model_ArrangementKindFromAbbreviation(model);
  pybind11_init_smtk_model_ArrangementKindFromName(model);
  pybind11_init_smtk_model_Dual(model);
  pybind11_init_smtk_model_ModelGeometryStyle(model);
  pybind11_init_smtk_model_ModelGeometryStyleName(model);
  pybind11_init_smtk_model_NameForArrangementKind(model);
  pybind11_init_smtk_model_NamedModelGeometryStyle(model);
  pybind11_init_smtk_model_SessionHasNoStaticSetup(model);
  pybind11_init_smtk_model_entityrefHash(model);
  pybind11_init_smtk_model_isCellEntity(model);
  pybind11_init_smtk_model_isChain(model);
  pybind11_init_smtk_model_isEdge(model);
  pybind11_init_smtk_model_isEdgeUse(model);
  pybind11_init_smtk_model_isFace(model);
  pybind11_init_smtk_model_isFaceUse(model);
  pybind11_init_smtk_model_isGroup(model);
  pybind11_init_smtk_model_isInstance(model);
  pybind11_init_smtk_model_isLoop(model);
  pybind11_init_smtk_model_isModel(model);
  pybind11_init_smtk_model_isSessionRef(model);
  pybind11_init_smtk_model_isShell(model);
  pybind11_init_smtk_model_isShellEntity(model);
  pybind11_init_smtk_model_isUseEntity(model);
  pybind11_init_smtk_model_isVertex(model);
  pybind11_init_smtk_model_isVertexUse(model);
  pybind11_init_smtk_model_isVolume(model);
  pybind11_init_smtk_model_isVolumeUse(model);
  pybind11_init_smtk_model_outcomeAsString(model);
  pybind11_init_smtk_model_stringToOutcome(model);
  PySharedPtrClass< smtk::model::AttributeListPhrase > smtk_model_AttributeListPhrase = pybind11_init_smtk_model_AttributeListPhrase(model, smtk_model_DescriptivePhrase);
  py::class_< smtk::model::CellEntity > smtk_model_CellEntity = pybind11_init_smtk_model_CellEntity(model, smtk_model_EntityRef);
  PySharedPtrClass< smtk::model::DefaultSession > smtk_model_DefaultSession = pybind11_init_smtk_model_DefaultSession(model, smtk_model_Session);
  PySharedPtrClass< smtk::model::EntityListPhrase > smtk_model_EntityListPhrase = pybind11_init_smtk_model_EntityListPhrase(model, smtk_model_DescriptivePhrase);
  PySharedPtrClass< smtk::model::EntityPhrase > smtk_model_EntityPhrase = pybind11_init_smtk_model_EntityPhrase(model, smtk_model_DescriptivePhrase);
  PySharedPtrClass< smtk::model::EntityTypeSubphrases > smtk_model_EntityTypeSubphrases = pybind11_init_smtk_model_EntityTypeSubphrases(model, smtk_model_SubphraseGenerator);
  py::class_< smtk::model::Group > smtk_model_Group = pybind11_init_smtk_model_Group(model, smtk_model_EntityRef);
  py::class_< smtk::model::Instance > smtk_model_Instance = pybind11_init_smtk_model_Instance(model, smtk_model_EntityRef);
  PySharedPtrClass< smtk::model::MeshListPhrase > smtk_model_MeshListPhrase = pybind11_init_smtk_model_MeshListPhrase(model, smtk_model_DescriptivePhrase);
  PySharedPtrClass< smtk::model::MeshPhrase > smtk_model_MeshPhrase = pybind11_init_smtk_model_MeshPhrase(model, smtk_model_DescriptivePhrase);
  py::class_< smtk::model::Model > smtk_model_Model = pybind11_init_smtk_model_Model(model, smtk_model_EntityRef);
  PySharedPtrClass< smtk::model::PropertyListPhrase > smtk_model_PropertyListPhrase = pybind11_init_smtk_model_PropertyListPhrase(model, smtk_model_DescriptivePhrase);
  PySharedPtrClass< smtk::model::PropertyValuePhrase > smtk_model_PropertyValuePhrase = pybind11_init_smtk_model_PropertyValuePhrase(model, smtk_model_DescriptivePhrase);
  PySharedPtrClass< smtk::model::RemoteOperator > smtk_model_RemoteOperator = pybind11_init_smtk_model_RemoteOperator(model, smtk_model_Operator);
  py::class_< smtk::model::SessionIOJSON > smtk_model_SessionIOJSON = pybind11_init_smtk_model_SessionIOJSON(model, smtk_model_SessionIO);
  py::class_< smtk::model::SessionRef > smtk_model_SessionRef = pybind11_init_smtk_model_SessionRef(model, smtk_model_EntityRef);
  py::class_< smtk::model::ShellEntity > smtk_model_ShellEntity = pybind11_init_smtk_model_ShellEntity(model, smtk_model_EntityRef);
  PySharedPtrClass< smtk::model::SimpleModelSubphrases > smtk_model_SimpleModelSubphrases = pybind11_init_smtk_model_SimpleModelSubphrases(model, smtk_model_SubphraseGenerator);
  py::class_< smtk::model::UseEntity > smtk_model_UseEntity = pybind11_init_smtk_model_UseEntity(model, smtk_model_EntityRef);
  py::class_< smtk::model::Chain > smtk_model_Chain = pybind11_init_smtk_model_Chain(model, smtk_model_ShellEntity);
  py::class_< smtk::model::Edge > smtk_model_Edge = pybind11_init_smtk_model_Edge(model, smtk_model_CellEntity);
  py::class_< smtk::model::EdgeUse > smtk_model_EdgeUse = pybind11_init_smtk_model_EdgeUse(model, smtk_model_UseEntity);
  py::class_< smtk::model::Face > smtk_model_Face = pybind11_init_smtk_model_Face(model, smtk_model_CellEntity);
  py::class_< smtk::model::FaceUse > smtk_model_FaceUse = pybind11_init_smtk_model_FaceUse(model, smtk_model_UseEntity);
  py::class_< smtk::model::Loop > smtk_model_Loop = pybind11_init_smtk_model_Loop(model, smtk_model_ShellEntity);
  py::class_< smtk::model::Shell > smtk_model_Shell = pybind11_init_smtk_model_Shell(model, smtk_model_ShellEntity);
  py::class_< smtk::model::Vertex > smtk_model_Vertex = pybind11_init_smtk_model_Vertex(model, smtk_model_CellEntity);
  py::class_< smtk::model::VertexUse > smtk_model_VertexUse = pybind11_init_smtk_model_VertexUse(model, smtk_model_UseEntity);
  py::class_< smtk::model::Volume > smtk_model_Volume = pybind11_init_smtk_model_Volume(model, smtk_model_CellEntity);
  py::class_< smtk::model::VolumeUse > smtk_model_VolumeUse = pybind11_init_smtk_model_VolumeUse(model, smtk_model_UseEntity);

  return model.ptr();
}
