/*
 * Copyright 2026 WebAssembly Community Group participants
 *
 * 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.
 */

//
// Prints the boundary - the imports and exports - in a convenient JSON format.
// Only enough information for JavaScript is provided (for the full info, parse
// the wat or wasm).
//
// Usage:
//
//    wasm-opt --print-boundary=OUTFILE
//
// If OUTFILE is not provided, prints to stdout.
//
// Example:
//
//  {
//    'imports': [
//      {
//        'module': 'foo', // foo.bar
//        'base': 'bar',
//        'kind': 'func',
//        'type': {
//          'params': ['i32', '(ref func)'],
//          'results': ['f64']
//        },
//      },
//      [..]
//    ],
//    'exports': [
//      {
//        'name': 'foo',
//        'kind': 'global',
//        'type': 'i32',
//      },
//      [..]
//    ]
//  }
//

#include "ir/module-utils.h"
#include "pass.h"
#include "support/file.h"
#include "support/json.h"
#include "wasm.h"

namespace wasm {

struct PrintBoundary : public Pass {
  bool modifiesBinaryenIR() override { return false; }

  void run(Module* module) override {
    std::string target = getArgumentOrDefault("print-boundary", "");

    // Imports.
    auto imports = json::Value::makeArray();

    ModuleUtils::iterImportable(
      *module, [&](ExternalKind kind, Importable* import) {
        auto item = json::Value::makeObject();
        item["module"] = json::Value::make(import->module.view());
        item["base"] = json::Value::make(import->base.view());
        item["kind"] = getKindName(kind);
        item["type"] = getExternalType(kind, import->name, *module);
        imports->push_back(item);
      });

    // Exports.
    auto exports = json::Value::makeArray();

    for (auto& exp : module->exports) {
      auto item = json::Value::makeObject();
      item["name"] = json::Value::make(exp->name.view());
      item["kind"] = getKindName(exp->kind);
      item["type"] =
        getExternalType(exp->kind, *exp->getInternalName(), *module);
      exports->push_back(item);
    }

    // Emit the final structure
    json::Value root;
    root.setObject();
    root["imports"] = imports;
    root["exports"] = exports;

    Output output(target, Flags::BinaryOption::Text);
    root.stringify(output.getStream(), true /* pretty */);
  }

  // Emits an array of multivalue types. For a signature, emits params and
  // results.
  //
  // We emit an array only when needed, unless forceArray is set.
  json::Value::Ref
  getTypes(Type type, bool forceArray = false, size_t depth = 0) {
    // Avoid infinite recursion.
    if (type.isRef() && depth == 0) {
      auto heapType = type.getHeapType();
      if (heapType.isSignature()) {
        auto sig = heapType.getSignature();
        auto ret = json::Value::makeObject();
        // Always emit arrays for params and results.
        ret["params"] = getTypes(sig.params, true, depth + 1);
        ret["results"] = getTypes(sig.results, true, depth + 1);
        return ret;
      }
    }

    // Simplify the output, avoiding an array for a single value.
    if (!forceArray && type.size() == 1) {
      return json::Value::make(type.toString());
    }

    auto ret = json::Value::makeArray();
    for (auto t : type) {
      ret->push_back(json::Value::make(t.toString()));
    }
    return ret;
  }

  // For an imported or exported thing (something external), and its name,
  // return the type info we report for it.
  json::Value::Ref getExternalType(ExternalKind kind, Name name, Module& wasm) {
    switch (kind) {
      case ExternalKind::Function:
        return getTypes(wasm.getFunction(name)->type);
      case ExternalKind::Table:
        return getTypes(wasm.getTable(name)->type);
      case ExternalKind::Memory:
        return getTypes(wasm.getMemory(name)->addressType);
      case ExternalKind::Global:
        return getTypes(wasm.getGlobal(name)->type);
      case ExternalKind::Tag:
        // Wrap it in a Type so that getTypes can handle it. That will print the
        // params and results as we expect.
        return getTypes(Type(wasm.getTag(name)->type, NonNullable));
      case ExternalKind::Invalid:
        break;
    }
    WASM_UNREACHABLE("invalid ExternalKind");
  }

  json::Value::Ref getKindName(ExternalKind kind) {
    const char* name = nullptr;
    switch (kind) {
      case ExternalKind::Function:
        name = "func";
        break;
      case ExternalKind::Table:
        name = "table";
        break;
      case ExternalKind::Memory:
        name = "memory";
        break;
      case ExternalKind::Global:
        name = "global";
        break;
      case ExternalKind::Tag:
        name = "tag";
        break;
      case ExternalKind::Invalid:
        WASM_UNREACHABLE("invalid ExternalKind");
    }
    return json::Value::make(name);
  }
};

Pass* createPrintBoundaryPass() { return new PrintBoundary(); }

} // namespace wasm
