// Copyright 2023 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

// Dumps parsed parameter file information.
// We intentionally use the same flags and parsing behavior as the rest of the
// runtime tools so that users can pass their parameter flags and see exactly
// what the runtime tools would see post-indexing. We don't try to dump original
// file metadata as we only support parsing enough information for what we need.
//
// We also support basic extraction of individual parameters in cases where
// users want to dump them out. Since we don't parse or preserve metadata we
// can't easily dump them to
//
// # List all available parameters and their index information:
// $ iree-dump-parameters --parameters=my_scope=my_file.gguf [--parameters=...]
// # Extract parameter binary contents from a file:
// $ iree-dump-parameters ... --extract=scope::key0=file0.bin [--extract=...]

#include <ctype.h>
#include <stdio.h>

#include "iree/base/api.h"
#include "iree/base/internal/file_io.h"
#include "iree/base/internal/flags.h"
#include "iree/io/parameter_index.h"
#include "iree/io/scope_map.h"
#include "iree/tooling/parameter_util.h"

//===----------------------------------------------------------------------===//
// Parameter extraction
//===----------------------------------------------------------------------===//

IREE_FLAG_LIST(string, extract,
               "Extracts a parameter to a file as `[scope::]key=file.bin`.");

static iree_status_t iree_tooling_extract_parameter(
    iree_io_scope_map_t* scope_map, iree_string_view_t scope,
    iree_string_view_t key, iree_string_view_t path,
    iree_allocator_t host_allocator) {
  // Lookup the index for the given scope.
  iree_io_parameter_index_t* index = NULL;  // unowned
  IREE_RETURN_IF_ERROR(iree_io_scope_map_lookup(scope_map, scope, &index));

  // Lookup the entry within the index.
  const iree_io_parameter_index_entry_t* entry = NULL;  // unowned
  IREE_RETURN_IF_ERROR(iree_io_parameter_index_lookup(index, key, &entry));

  fprintf(stdout, "Extracting parameter `");
  if (!iree_string_view_is_empty(scope)) {
    fprintf(stdout, "%.*s::", (int)scope.size, scope.data);
  }
  fprintf(stdout, "%.*s` (%" PRIu64 "b) to `%.*s`...\n", (int)key.size,
          key.data, entry->length, (int)path.size, path.data);

  if (entry->type != IREE_IO_PARAMETER_INDEX_ENTRY_STORAGE_TYPE_FILE) {
    return iree_make_status(IREE_STATUS_FAILED_PRECONDITION,
                            "cannot extract parameters of type %d",
                            (int)entry->type);
  }

  // TODO(benvanik): support generic file handle IO instead of memory-only.
  if (iree_io_file_handle_type(entry->storage.file.handle) !=
      IREE_IO_FILE_HANDLE_TYPE_HOST_ALLOCATION) {
    return iree_make_status(
        IREE_STATUS_UNIMPLEMENTED,
        "only host allocation file handles are supported today");
  }
  iree_byte_span_t file_contents =
      iree_io_file_handle_value(entry->storage.file.handle).host_allocation;
  iree_const_byte_span_t entry_contents = iree_make_const_byte_span(
      file_contents.data + entry->storage.file.offset, entry->length);
  char* path_str = (char*)iree_alloca(path.size + 1);
  memcpy(path_str, path.data, path.size);
  path_str[path.size] = 0;
  return iree_file_write_contents(path_str, entry_contents);
}

static iree_status_t iree_tooling_extract_parameters(
    iree_io_scope_map_t* scope_map, iree_allocator_t host_allocator) {
  for (iree_host_size_t i = 0; i < FLAG_extract_list().count; ++i) {
    iree_string_view_t flag = FLAG_extract_list().values[i];
    iree_string_view_t identifier, path;
    iree_string_view_split(flag, '=', &identifier, &path);

    iree_host_size_t separator_pos =
        iree_string_view_find_first_of(identifier, IREE_SV("::"), 0);
    iree_string_view_t scope = iree_string_view_empty();
    iree_string_view_t key = iree_string_view_empty();
    if (separator_pos != IREE_STRING_VIEW_NPOS) {
      scope = iree_string_view_substr(identifier, 0, separator_pos);
      key = iree_string_view_substr(identifier, separator_pos + 2,
                                    IREE_HOST_SIZE_MAX);
    } else {
      key = identifier;
    }

    IREE_RETURN_IF_ERROR(iree_tooling_extract_parameter(scope_map, scope, key,
                                                        path, host_allocator),
                         "extracting parameter with flag `%.*s`",
                         (int)flag.size, flag.data);
  }
  return iree_ok_status();
}

//===----------------------------------------------------------------------===//
// main
//===----------------------------------------------------------------------===//

int main(int argc, char** argv) {
  IREE_TRACE_APP_ENTER();
  IREE_TRACE_ZONE_BEGIN(z0);

  iree_allocator_t host_allocator = iree_allocator_system();
  int exit_code = EXIT_SUCCESS;

  // Parse command line flags.
  iree_flags_set_usage("iree-dump-parameters",
                       "Dumps information about parsed parameter files.\n");
  iree_flags_parse_checked(IREE_FLAGS_PARSE_MODE_DEFAULT, &argc, &argv);

  if (argc > 1) {
    fprintf(stderr, "Error: no positional arguments expected.\n");
    fprintf(stderr,
            "Use one or more --parameters=file.ext flags to specify parameter "
            "files.\n");
    IREE_TRACE_ZONE_END(z0);
    IREE_TRACE_APP_EXIT(exit_code);
    return EXIT_FAILURE;
  }

  iree_io_scope_map_t scope_map = {0};
  iree_io_scope_map_initialize(host_allocator, &scope_map);

  // Parse parameters using the common tooling flags.
  iree_status_t status =
      iree_tooling_build_parameter_indices_from_flags(&scope_map);

  // Dump parameter information.
  if (iree_status_is_ok(status)) {
    iree_string_builder_t sb;
    iree_string_builder_initialize(host_allocator, &sb);
    status = iree_io_scope_map_dump(&scope_map, &sb);
    if (iree_status_is_ok(status)) {
      fprintf(stdout, "%.*s", (int)iree_string_builder_size(&sb),
              iree_string_builder_buffer(&sb));
    }
    iree_string_builder_deinitialize(&sb);
  }

  // Extract parameters as requested, if any.
  if (iree_status_is_ok(status)) {
    status = iree_tooling_extract_parameters(&scope_map, host_allocator);
  }

  iree_io_scope_map_deinitialize(&scope_map);

  fflush(stdout);
  if (!iree_status_is_ok(status)) {
    iree_status_fprint(stderr, status);
    iree_status_free(status);
    exit_code = EXIT_FAILURE;
  }
  fflush(stderr);

  IREE_TRACE_ZONE_END(z0);
  IREE_TRACE_APP_EXIT(exit_code);
  return exit_code;
}
