//=========================================================================
//  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.
//=========================================================================

#ifndef pybind_smtk_model_Operator_h
#define pybind_smtk_model_Operator_h

#include <pybind11/pybind11.h>

#include "smtk/model/Operator.h"

#include "smtk/attribute/Definition.h"
#include "smtk/attribute/DirectoryItem.h"
#include "smtk/attribute/DoubleItem.h"
#include "smtk/attribute/FileItem.h"
#include "smtk/attribute/GroupItem.h"
#include "smtk/attribute/IntItem.h"
#include "smtk/attribute/MeshItem.h"
#include "smtk/attribute/MeshSelectionItem.h"
#include "smtk/attribute/RefItem.h"
#include "smtk/attribute/StringItem.h"
#include "smtk/attribute/VoidItem.h"

namespace py = pybind11;

PySharedPtrClass< smtk::model::Operator > pybind11_init_smtk_model_Operator(py::module &m)
{
  py::enum_<smtk::model::OperatorOutcome>(m, "OperatorOutcome")
    .value("UNABLE_TO_OPERATE", smtk::model::UNABLE_TO_OPERATE)
    .value("OPERATION_CANCELED", smtk::model::OPERATION_CANCELED)
    .value("OPERATION_FAILED", smtk::model::OPERATION_FAILED)
    .value("OPERATION_SUCCEEDED", smtk::model::OPERATION_SUCCEEDED)
    .value("OUTCOME_UNKNOWN", smtk::model::OUTCOME_UNKNOWN)
    .export_values();

  PySharedPtrClass< smtk::model::Operator > instance(m, "Operator");
  instance
    .def("__lt__", (bool (smtk::model::Operator::*)(::smtk::model::Operator const &) const) &smtk::model::Operator::operator<)
    .def("deepcopy", (smtk::model::Operator & (smtk::model::Operator::*)(::smtk::model::Operator const &)) &smtk::model::Operator::operator=)
    .def_property("manager", &smtk::model::Operator::manager, &smtk::model::Operator::setManager)
    .def_property("meshManager", &smtk::model::Operator::meshManager, &smtk::model::Operator::setMeshManager)
    .def_property("specification", &smtk::model::Operator::specification, &smtk::model::Operator::setSpecification)
    .def_property("session", &smtk::model::Operator::session, &smtk::model::Operator::setSession)
    .def("ableToOperate", &smtk::model::Operator::ableToOperate)
    .def("associateEntity", &smtk::model::Operator::associateEntity, py::arg("entity"))
    .def("className", &smtk::model::Operator::className)
    .def("classname", &smtk::model::Operator::classname)
    .def("createResult", &smtk::model::Operator::createResult, py::arg("outcome") = ::smtk::model::UNABLE_TO_OPERATE)
    .def("definition", &smtk::model::Operator::definition)
    .def("disassociateEntity", &smtk::model::Operator::disassociateEntity, py::arg("entity"))
    .def("ensureSpecification", &smtk::model::Operator::ensureSpecification)
    .def("eraseResult", &smtk::model::Operator::eraseResult, py::arg("res"))
    .def("findDirectory", &smtk::model::Operator::findDirectory, py::arg("name"), py::arg("style") = ::smtk::attribute::ALL_CHILDREN)
    .def("findDouble", &smtk::model::Operator::findDouble, py::arg("name"), py::arg("style") = ::smtk::attribute::ALL_CHILDREN)
    .def("findFile", &smtk::model::Operator::findFile, py::arg("name"), py::arg("style") = ::smtk::attribute::ALL_CHILDREN)
    .def("findGroup", &smtk::model::Operator::findGroup, py::arg("name"), py::arg("style") = ::smtk::attribute::ALL_CHILDREN)
    .def("findInt", &smtk::model::Operator::findInt, py::arg("name"), py::arg("style") = ::smtk::attribute::ALL_CHILDREN)
    .def("findMesh", &smtk::model::Operator::findMesh, py::arg("name"), py::arg("style") = ::smtk::attribute::ALL_CHILDREN)
    .def("findMeshSelection", &smtk::model::Operator::findMeshSelection, py::arg("name"), py::arg("style") = ::smtk::attribute::ALL_CHILDREN)
    .def("findModelEntity", &smtk::model::Operator::findModelEntity, py::arg("name"), py::arg("style") = ::smtk::attribute::ALL_CHILDREN)
    .def("findRef", &smtk::model::Operator::findRef, py::arg("name"), py::arg("style") = ::smtk::attribute::ALL_CHILDREN)
    .def("findString", &smtk::model::Operator::findString, py::arg("name"), py::arg("style") = ::smtk::attribute::ALL_CHILDREN)
    .def("findVoid", &smtk::model::Operator::findVoid, py::arg("name"), py::arg("style") = ::smtk::attribute::ALL_CHILDREN)
    .def("log", &smtk::model::Operator::log)
    .def("name", &smtk::model::Operator::name)
    .def("observe", (void (smtk::model::Operator::*)(::smtk::model::OperatorEventType, ::smtk::model::BareOperatorCallback, void *)) &smtk::model::Operator::observe, py::arg("event"), py::arg("functionHandle"), py::arg("callData"))
    .def("observe", (void (smtk::model::Operator::*)(::smtk::model::OperatorEventType, ::smtk::model::OperatorWithResultCallback, void *)) &smtk::model::Operator::observe, py::arg("event"), py::arg("functionHandle"), py::arg("callData"))
    .def("operate", &smtk::model::Operator::operate)
    .def("removeAllAssociations", &smtk::model::Operator::removeAllAssociations)
    .def("trigger", (int (smtk::model::Operator::*)(::smtk::model::OperatorEventType)) &smtk::model::Operator::trigger, py::arg("event"))
    .def("trigger", (int (smtk::model::Operator::*)(::smtk::model::OperatorEventType, ::smtk::model::OperatorResult const &)) &smtk::model::Operator::trigger, py::arg("event"), py::arg("result"))
    .def("unobserve", (void (smtk::model::Operator::*)(::smtk::model::OperatorEventType, ::smtk::model::BareOperatorCallback, void *)) &smtk::model::Operator::unobserve, py::arg("event"), py::arg("functionHandle"), py::arg("callData"))
    .def("unobserve", (void (smtk::model::Operator::*)(::smtk::model::OperatorEventType, ::smtk::model::OperatorWithResultCallback, void *)) &smtk::model::Operator::unobserve, py::arg("event"), py::arg("functionHandle"), py::arg("callData"))
    .def("findAsInt", [](const smtk::model::Operator& o, const std::string& s) {
        return o.specification()->findAs<smtk::attribute::IntItem>(s, smtk::attribute::ALL_CHILDREN); })
    .def("findAsDouble", [](const smtk::model::Operator& o, const std::string& s) {
        return o.specification()->findAs<smtk::attribute::DoubleItem>(s, smtk::attribute::ALL_CHILDREN); })
    .def("findAsString", [](const smtk::model::Operator& o, const std::string& s) {
        return o.specification()->findAs<smtk::attribute::StringItem>(s, smtk::attribute::ALL_CHILDREN); })
    .def("findAsFile", [](const smtk::model::Operator& o, const std::string& s) {
        return o.specification()->findAs<smtk::attribute::FileItem>(s, smtk::attribute::ALL_CHILDREN); })
    .def("findAsDirectory", [](const smtk::model::Operator& o, const std::string& s) {
        return o.specification()->findAs<smtk::attribute::DirectoryItem>(s, smtk::attribute::ALL_CHILDREN); })
    .def("findAsGroup", [](const smtk::model::Operator& o, const std::string& s) {
        return o.specification()->findAs<smtk::attribute::GroupItem>(s, smtk::attribute::ALL_CHILDREN); })
    .def("findAsRef", [](const smtk::model::Operator& o, const std::string& s) {
        return o.specification()->findAs<smtk::attribute::RefItem>(s, smtk::attribute::ALL_CHILDREN); })
    .def("findAsModelEntity", [](const smtk::model::Operator& o, const std::string& s) {
        return o.specification()->findAs<smtk::attribute::ModelEntityItem>(s, smtk::attribute::ALL_CHILDREN); })
    ;
  py::enum_<smtk::model::Operator::ResultEntityOrigin>(instance, "ResultEntityOrigin")
    .value("CREATED", smtk::model::Operator::ResultEntityOrigin::CREATED)
    .value("MODIFIED", smtk::model::Operator::ResultEntityOrigin::MODIFIED)
    .value("EXPUNGED", smtk::model::Operator::ResultEntityOrigin::EXPUNGED)
    .value("UNKNOWN", smtk::model::Operator::ResultEntityOrigin::UNKNOWN)
    .export_values();
  return instance;
}

void pybind11_init_smtk_model_outcomeAsString(py::module &m)
{
  m.def("outcomeAsString", &smtk::model::outcomeAsString, "", py::arg("oc"));
}

void pybind11_init_smtk_model_stringToOutcome(py::module &m)
{
  m.def("stringToOutcome", &smtk::model::stringToOutcome, "", py::arg("oc"));
}

#endif
