/*
 * Copyright 2023 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
 *
 *     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.
 */

// Person_detection quant model
// MlModel struct initialization to include model I/O info.
// Bytecode loading, input/output processes.

#include "person_detection.h"

#include <log.h>

// Compiled module embedded here to avoid file IO:
#if defined(BUILD_VMVX)
#if !defined(BUILD_EMITC)
#include "person_detection_bytecode_module_vmvx_c.h"
#else
#include "person_detection_c_module_vmvx_emitc.h"
#endif  // !defined(BUILD_EMITC)
#else
#if !defined(BUILD_EMITC)
#include "person_detection_bytecode_module_static.h"
#include "person_detection_bytecode_module_static_c.h"
#else
#include "person_detection_c_module_static_c.h"
#include "person_detection_c_module_static_emitc.h"
#endif  // !defined(BUILD_EMITC)
#endif  // defined(BUILD_VMVX)
#include "person_detection_quant_input_c.h"

__attribute__((section(".model_output"))) PersonDetectionOutput detection;

iree_status_t create_module(iree_vm_instance_t *instance,
                            iree_vm_module_t **module) {
#if !defined(BUILD_EMITC)
#if defined(BUILD_VMVX)
  const struct iree_file_toc_t *module_file_toc =
      quant_models_person_detection_bytecode_module_vmvx_create();
#else
  const struct iree_file_toc_t *module_file_toc =
      quant_models_person_detection_bytecode_module_static_create();
#endif
  return iree_vm_bytecode_module_create(
      instance,
      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
      iree_allocator_null(), iree_allocator_system(), module);
#else
  return module_create(instance, iree_allocator_system(), module);
#endif
}

#if !defined(BUILD_VMVX)
iree_hal_executable_library_query_fn_t library_query(void) {
  return &llvm_module_linked_llvm_cpu_library_query;
}
#endif

iree_status_t load_input_data(const MlModel *model, void **buffer,
                              iree_const_byte_span_t **byte_span) {
  byte_span[0] = malloc(sizeof(iree_const_byte_span_t));
  *byte_span[0] = iree_make_const_byte_span(
      person_detection_quant_input,
      model->input_size_bytes[0] * model->input_length[0]);
  return iree_ok_status();
}

iree_status_t process_output(const MlModel *model,
                             iree_hal_buffer_mapping_t *buffers,
                             uint32_t *output_length, uint32_t *output_ptr) {
  iree_status_t result = iree_ok_status();
  int8_t *data = (int8_t *)buffers[0].contents.data;
  detection.non_person_score = data[0];
  detection.person_score = data[1];

  LOG_INFO("Output: Non-person Score: %d; Person Score: %d",
           detection.non_person_score, detection.person_score);

  *output_length = sizeof(detection);
  *output_ptr = (uint32_t)&detection;
  return result;
}
