// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "bindings/python/pyiree/rt.h"

#include "bindings/python/pyiree/status_utils.h"
#include "iree/base/api.h"
#include "iree/hal/api.h"

namespace iree {
namespace python {

HalBufferView RtContext::WrapPyBufferForInput(py::buffer py_buffer) {
  auto py_buffer_info = py_buffer.request(false /* writable */);
  if (py_buffer_info.ndim > IREE_SHAPE_MAX_RANK || py_buffer_info.ndim < 0) {
    RaiseValueError("Unsupported buffer rank");
  }
  if (py_buffer_info.size < 0) {
    RaiseValueError("Illegal buffer size");
  }

  // For the moment, allocate a device visible buffer of equivalent size and
  // copy into it.
  // TODO(laurenzo): Once sequencer is in place, switch to HeapBuffer, wrap
  // and retain the original buffer.
  iree_host_size_t byte_size = py_buffer_info.size * py_buffer_info.itemsize;
  HalBuffer buffer =
      AllocateDeviceVisible(byte_size, IREE_HAL_BUFFER_USAGE_ALL);
  CheckApiStatus(iree_hal_buffer_write_data(buffer.raw_ptr(), 0,
                                            py_buffer_info.ptr, byte_size),
                 "Error writing to input buffer");

  // Create the buffer view.
  // TODO(laurenzo): This does no validation on dtype and only cares if the
  // elementsize matches. Figure out where to enforce actual dtype.
  iree_shape_t shape;
  shape.rank = py_buffer_info.ndim;

  // Verify strides are row-major.
  // TODO(laurenzo): Test this with rank>1.
  for (int i = 1; i < shape.rank; ++i) {
    if ((py_buffer_info.strides[i - 1] * py_buffer_info.itemsize) !=
        py_buffer_info.shape[i]) {
      RaiseValueError("Expected row-major layout");
    }
  }
  if (!py_buffer_info.strides.empty()) {
    if (py_buffer_info.strides.back() != 1) {
      RaiseValueError("Expected row-major layout");
    }
  }

  // Populate shape.
  for (int i = 0; i < shape.rank; ++i) {
    ssize_t dim = py_buffer_info.shape[i];
    if (dim < 0) {
      RaiseValueError("Unsupported negative dim");
    }
    shape.dims[i] = dim;
  }

  iree_hal_buffer_view_t* bv;
  CheckApiStatus(iree_hal_buffer_view_create(buffer.raw_ptr(), shape,
                                             py_buffer_info.itemsize,
                                             IREE_ALLOCATOR_DEFAULT, &bv),
                 "Error allocating buffer view");

  return HalBufferView::CreateRetained(bv);
}

void SetupRtBindings(pybind11::module m) {
  // BufferPlacement.
  py::enum_<BufferPlacement>(m, "BufferPlacement")
      .value("HEAP", BufferPlacement::kHeap)
      .value("DEVICE_VISIBLE", BufferPlacement::kDeviceVisible)
      .value("DEVICE_LOCAL", BufferPlacement::kDeviceLocal)
      .export_values();

  // RtModule.
  py::class_<RtModule>(m, "Module")
      .def_property_readonly("name", &RtModule::name)
      .def("lookup_function_by_ordinal", &RtModule::lookup_function_by_ordinal)
      .def("lookup_function_by_name", &RtModule::lookup_function_by_name);
  // RtFunction.
  py::class_<RtFunction>(m, "Function")
      .def_property_readonly("name", &RtFunction::name)
      .def_property_readonly("signature", &RtFunction::signature);
  py::class_<iree_rt_function_signature_t>(m, "FunctionSignature")
      .def_readonly("argument_count",
                    &iree_rt_function_signature_t::argument_count)
      .def_readonly("result_count",
                    &iree_rt_function_signature_t::result_count);

  // RtPolicy.
  py::class_<RtPolicy>(m, "Policy").def(py::init(&RtPolicy::Create));

  // RtInstance.
  py::class_<RtInstance>(m, "Instance")
      .def(py::init(&RtInstance::Create),
           py::arg_v("driver_name", absl::optional<std::string>()));

  // RtContext.
  py::class_<RtContext>(m, "Context")
      .def(py::init(&RtContext::Create), py::arg("instance"), py::arg("policy"))
      .def_property_readonly("context_id", &RtContext::context_id)
      .def("register_modules", &RtContext::RegisterModules, py::arg("modules"))
      .def("register_module", &RtContext::RegisterModule, py::arg("module"))
      .def("lookup_module_by_name", &RtContext::LookupModuleByName,
           py::arg("name"))
      .def("resolve_function", &RtContext::ResolveFunction,
           py::arg("full_name"))
      .def("allocate", &RtContext::Allocate, py::arg("allocation_size"),
           py::arg("placement") = BufferPlacement::kHeap,
           py::arg("usage") = IREE_HAL_BUFFER_USAGE_ALL)
      .def("allocate_device_local", &RtContext::AllocateDeviceLocal,
           py::arg("allocation_size"),
           py::arg("usage") = IREE_HAL_BUFFER_USAGE_ALL)
      .def("allocate_device_visible", &RtContext::AllocateDeviceVisible,
           py::arg("allocation_size"),
           py::arg("usage") = IREE_HAL_BUFFER_USAGE_ALL)
      .def("wrap_for_input", &RtContext::WrapPyBufferForInput, py::arg("v"))
      .def("invoke", &RtContext::Invoke, py::arg("f"), py::arg("policy"),
           py::arg("arguments"),
           py::arg("results") = absl::optional<std::vector<HalBufferView*>>());

  // RtInvocation.
  py::class_<RtInvocation>(m, "Invocation")
      .def("query_status", &RtInvocation::QueryStatus)
      .def("await_ready", &RtInvocation::Await,
           py::arg("deadline") = IREE_TIME_INFINITE_FUTURE)
      .def("await_ready_optional", &RtInvocation::AwaitOptional,
           py::arg("deadline") = IREE_TIME_INFINITE_FUTURE)
      .def_property_readonly("results", &RtInvocation::ConsumeResults);
}

}  // namespace python
}  // namespace iree
