/* Copyright 2022 The TensorFlow Authors. All Rights Reserved.

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

    http://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 "python/tflite_micro/interpreter_wrapper.h"

// Disallow Numpy 1.7 deprecated symbols.
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
// See https://numpy.org/doc/1.16/reference/c-api.array.html#importing-the-api
#define NO_IMPORT_ARRAY
#define PY_ARRAY_UNIQUE_SYMBOL tflite_micro_python_interpreter_array_api
#include <numpy/arrayobject.h>
#include <pybind11/pybind11.h>

#include "python/tflite_micro/numpy_utils.h"
#include "python/tflite_micro/pybind11_lib.h"
#include "python/tflite_micro/python_ops_resolver.h"
#include "python/tflite_micro/python_utils.h"
#include "python/tflite_micro/shared_library.h"
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/micro/recording_micro_allocator.h"

namespace tflite {
namespace {
// This function looks up the registerer symbol based on the string name
// `registerer_name`. A registerer in this case is a function that calls the
// `AddCustom` API of `PythonOpsResolver` for custom ops that need to be
// registered with the interpreter.
bool AddCustomOpRegistererByName(const char* registerer_name,
                                 tflite::PythonOpsResolver* resolver) {
  // Registerer functions take a pointer to a PythonOpsResolver as an input
  // parameter and return TfLiteStatus.
  typedef bool (*RegistererFunctionType)(tflite::PythonOpsResolver*);

  // Look for the Registerer function by name.
  RegistererFunctionType registerer = reinterpret_cast<RegistererFunctionType>(
      SharedLibrary::GetSymbol(registerer_name));

  // Fail in an informative way if the function was not found.
  if (registerer == nullptr) {
    MicroPrintf("Looking up symbol '%s' failed with error '%s'.",
                registerer_name, SharedLibrary::GetError());
    return false;
  }

  // Call the registerer with the resolver.
  if (!registerer(resolver)) {
    MicroPrintf(
        "%s failed to register op. Check that total number of "
        "ops doesn't exceed the maximum allowed by PythonOpsResolver.",
        registerer_name);
    return false;
  }

  return true;
}

PyObject* PyArrayFromFloatVector(const float* data, npy_intp size) {
  void* pydata = malloc(size * sizeof(float));
  memcpy(pydata, data, size * sizeof(float));
  PyObject* obj = PyArray_SimpleNewFromData(1, &size, NPY_FLOAT32, pydata);
  PyArray_ENABLEFLAGS(reinterpret_cast<PyArrayObject*>(obj), NPY_ARRAY_OWNDATA);
  return obj;
}

PyObject* PyArrayFromIntVector(const int* data, npy_intp size) {
  void* pydata = malloc(size * sizeof(int));
  memcpy(pydata, data, size * sizeof(int));
  PyObject* obj = PyArray_SimpleNewFromData(1, &size, NPY_INT32, pydata);
  PyArray_ENABLEFLAGS(reinterpret_cast<PyArrayObject*>(obj), NPY_ARRAY_OWNDATA);
  return obj;
}

// Check if the tensor is valid for TFLM
bool CheckTensor(const TfLiteTensor* tensor) {
  if (tensor == nullptr) {
    PyErr_SetString(PyExc_IndexError,
                    "Tensor is out of bound, please check tensor index.");
    return false;
  }

  if (tensor->type == kTfLiteString || tensor->type == kTfLiteResource ||
      tensor->type == kTfLiteVariant) {
    PyErr_SetString(PyExc_ValueError,
                    "TFLM doesn't support strings, resource variables, or "
                    "variants as outputs.");
    return false;
  }

  if (tensor->sparsity != nullptr) {
    PyErr_SetString(PyExc_ValueError, "TFLM doesn't support sparse tensors");
    return false;
  }

  int py_type_num = TfLiteTypeToPyArrayType(tensor->type);
  if (py_type_num == NPY_NOTYPE) {
    PyErr_SetString(PyExc_ValueError, "Unknown tensor type.");
    return false;
  }

  if (tensor->bytes == 0 && tensor->data.data != nullptr) {
    PyErr_SetString(PyExc_ValueError, "Invalid tensor size of 0.");
    return false;
  }

  if (tensor->bytes > 0 && tensor->data.data == nullptr) {
    PyErr_SetString(PyExc_ValueError, "Null tensor pointer.");
    return false;
  }
  return true;
}

PyObject* GetTensorSize(const TfLiteTensor* tensor) {
  PyObject* np_array =
      PyArrayFromIntVector(tensor->dims->data, tensor->dims->size);

  return PyArray_Return(reinterpret_cast<PyArrayObject*>(np_array));
}

PyObject* GetTensorType(const TfLiteTensor* tensor) {
  int code = TfLiteTypeToPyArrayType(tensor->type);
  return PyArray_TypeObjectFromType(code);
}

// Create a python dictionary object that contains the general (can be
// channel-wise quantized) affiene quantization information about the tensor.
PyObject* GetTensorQuantizationParameters(const TfLiteTensor* tensor) {
  const TfLiteQuantization quantization = tensor->quantization;
  float* scales_data = nullptr;
  int32_t* zero_points_data = nullptr;
  int32_t scales_size = 0;
  int32_t zero_points_size = 0;
  int32_t quantized_dimension = 0;
  if (quantization.type == kTfLiteAffineQuantization) {
    const TfLiteAffineQuantization* q_params =
        reinterpret_cast<const TfLiteAffineQuantization*>(quantization.params);
    if (q_params->scale) {
      scales_data = q_params->scale->data;
      scales_size = q_params->scale->size;
    }
    if (q_params->zero_point) {
      zero_points_data = q_params->zero_point->data;
      zero_points_size = q_params->zero_point->size;
    }
    quantized_dimension = q_params->quantized_dimension;
  }
  PyObject* scales_array = PyArrayFromFloatVector(scales_data, scales_size);
  PyObject* zero_points_array =
      PyArrayFromIntVector(zero_points_data, zero_points_size);

  PyObject* result = PyDict_New();
  PyDict_SetItemString(result, "scales", scales_array);
  PyDict_SetItemString(result, "zero_points", zero_points_array);
  PyDict_SetItemString(result, "quantized_dimension",
                       PyLong_FromLong(quantized_dimension));
  return result;
}

PyObject* GetTensorDetails(const TfLiteTensor* tensor) {
  if (!CheckTensor(tensor)) {
    return nullptr;
  }

  PyObject* tensor_type = GetTensorType(tensor);
  PyObject* tensor_size = GetTensorSize(tensor);
  PyObject* tensor_quantization_parameters =
      GetTensorQuantizationParameters(tensor);

  PyObject* result = PyDict_New();
  PyDict_SetItemString(result, "dtype", tensor_type);
  PyDict_SetItemString(result, "shape", tensor_size);
  PyDict_SetItemString(result, "quantization_parameters",
                       tensor_quantization_parameters);

  return result;
}

}  // namespace

InterpreterWrapper::~InterpreterWrapper() {
  // We don't use a unique_ptr for the interpreter because we need to call its
  // destructor before we call Py_DECREF(model_). This ensures that the model
  // is still in scope when MicroGraph:FreeSubgraphs() is called. Otherwise,
  // a segmentation fault could occur.
  if (interpreter_ != nullptr) {
    delete interpreter_;
  }

  // Undo any references incremented
  Py_DECREF(model_);
}

InterpreterWrapper::InterpreterWrapper(
    PyObject* model_data, const std::vector<std::string>& registerers_by_name,
    size_t arena_size, int num_resource_variables) {
  interpreter_ = nullptr;

  // `model_data` is used as a raw pointer beyond the scope of this
  // constructor, so we need to increment the reference count so that Python
  // doesn't destroy it during the lifetime of this interpreter.
  Py_INCREF(model_data);

  // Get the input array contained in `model_data` as a byte array
  char* buf = nullptr;
  Py_ssize_t length;
  if (ConvertFromPyString(model_data, &buf, &length) == -1 || buf == nullptr) {
    ThrowValueError(
        "TFLM cannot convert model data from Python object to char *");
  }

  const Model* model = GetModel(buf);
  model_ = model_data;
  memory_arena_ = std::unique_ptr<uint8_t[]>(new uint8_t[arena_size]);
  allocator_ = RecordingMicroAllocator::Create(memory_arena_.get(), arena_size);
  MicroResourceVariables* resource_variables_ = nullptr;
  if (num_resource_variables > 0)
    resource_variables_ =
        MicroResourceVariables::Create(allocator_, num_resource_variables);

  for (const std::string& registerer : registerers_by_name) {
    if (!AddCustomOpRegistererByName(registerer.c_str(),
                                     &python_ops_resolver_)) {
      ThrowRuntimeError(
          ("TFLM could not register custom op via " + registerer).c_str());
    }
  }

  interpreter_ = new MicroInterpreter(model, python_ops_resolver_, allocator_,
                                      resource_variables_);

  TfLiteStatus status = interpreter_->AllocateTensors();
  if (status != kTfLiteOk) {
    ThrowRuntimeError("TFLM failed to allocate tensors");
  }

  // This must be called before using any PyArray_* APIs. It essentially sets
  // up the lookup table that maps PyArray_* macros to the correct APIs.
  ImportNumpy();
}

void InterpreterWrapper::PrintAllocations() { allocator_->PrintAllocations(); }

int InterpreterWrapper::Invoke() {
  TfLiteStatus status = interpreter_->Invoke();
  if (status == kTfLiteError) {
    ThrowRuntimeError("Interpreter invocation failed.");
  }
  return status;
}

int InterpreterWrapper::Reset() { return interpreter_->Reset(); }

// 1. Check that tensor and input array are safe to access
// 2. Verify that input array metadata matches tensor metadata
// 3. Copy input buffer into target input tensor
void InterpreterWrapper::SetInputTensor(PyObject* data, size_t index) {
  std::unique_ptr<PyObject, PyDecrefDeleter> array_safe(PyArray_FromAny(
      /*op=*/data,
      /*dtype=*/nullptr,
      /*min_depth=*/0,
      /*max_depth=*/0,
      /*requirements=*/NPY_ARRAY_CARRAY,
      /*context=*/nullptr));
  if (!array_safe) {
    ThrowValueError("TFLM cannot convert input to PyArray");
  }

  PyArrayObject* array = reinterpret_cast<PyArrayObject*>(array_safe.get());

  TfLiteTensor* tensor = interpreter_->input(index);
  if (!CheckTensor(tensor)) {
    throw pybind11::error_already_set();
  }

  if (TfLiteTypeFromPyArray(array) != tensor->type) {
    std::string err_str =
        "Cannot set tensor: Got value of type " +
        std::string(TfLiteTypeGetName(TfLiteTypeFromPyArray(array))) +
        " but expected type " + TfLiteTypeGetName(tensor->type) +
        " for input " + std::to_string(index);
    ThrowValueError(err_str.c_str());
  }

  if (PyArray_NDIM(array) != tensor->dims->size) {
    std::string err_str = "Cannot set tensor: Dimension mismatch. Got " +
                          std::to_string(PyArray_NDIM(array)) +
                          " but expected " +
                          std::to_string(tensor->dims->size) + " for input " +
                          std::to_string(index);
    ThrowValueError(err_str.c_str());
  }

  for (int j = 0; j < PyArray_NDIM(array); j++) {
    if (tensor->dims->data[j] != PyArray_SHAPE(array)[j]) {
      std::string err_str =
          "Cannot set tensor: Dimension mismatch. Got " +
          std::to_string(PyArray_SHAPE(array)[j]) + " but expected " +
          std::to_string(tensor->dims->data[j]) + " for dimension " +
          std::to_string(j) + " of input " + std::to_string(index);
      ThrowValueError(err_str.c_str());
    }
  }

  if (tensor->data.data == nullptr && tensor->bytes) {
    ThrowValueError("Cannot set tensor: Tensor is non-empty but has nullptr.");
  }

  size_t size = PyArray_NBYTES(array);
  if (size != tensor->bytes) {
    std::string err_str = "numpy array had " + std::to_string(size) +
                          " bytes but expected " +
                          std::to_string(tensor->bytes) + " bytes.";
    ThrowValueError(err_str.c_str());
  }

  memcpy(tensor->data.data, PyArray_DATA(array), size);
}

// 1. Check that output tensor is supported and safe to access
// 2. Allocate a buffer and copy output tensor data into it
// 3. Set PyArray metadata and transfer ownership to caller
PyObject* InterpreterWrapper::GetOutputTensor(size_t index) const {
  const TfLiteTensor* tensor = interpreter_->output(index);
  if (!CheckTensor(tensor)) {
    return nullptr;
  }
  // Allocate a new buffer with output data to be returned to Python. New memory
  // is allocated here to prevent hard to debug issues in Python, like data
  // potentially changing under the hood, which imposes an implicit requirement
  // that the user needs to be aware of.
  void* data = malloc(tensor->bytes);
  memcpy(data, tensor->data.data, tensor->bytes);

  PyObject* np_array;
  std::vector<npy_intp> dims(tensor->dims->data,
                             tensor->dims->data + tensor->dims->size);
  int py_type_num = TfLiteTypeToPyArrayType(tensor->type);
  np_array =
      PyArray_SimpleNewFromData(dims.size(), dims.data(), py_type_num, data);

  // Transfer ownership to Python so that there's Python will take care of
  // releasing this buffer
  PyArray_ENABLEFLAGS(reinterpret_cast<PyArrayObject*>(np_array),
                      NPY_ARRAY_OWNDATA);

  return PyArray_Return(reinterpret_cast<PyArrayObject*>(np_array));
}

PyObject* InterpreterWrapper::GetInputTensorDetails(size_t index) const {
  return GetTensorDetails(interpreter_->input(index));
}

PyObject* InterpreterWrapper::GetOutputTensorDetails(size_t index) const {
  return GetTensorDetails(interpreter_->output(index));
}

}  // namespace tflite
