// 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_SYSTEM, &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
