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

#include "contexts.h"

namespace wasm::WATParser {

namespace {

void applyImportNames(Importable& item, ImportNames* names) {
  if (names) {
    item.module = names->mod;
    item.base = names->nm;
  }
}

Result<> addExports(ParseInput& in,
                    Module& wasm,
                    const Named* item,
                    const std::vector<Name>& exports,
                    ExternalKind kind) {
  for (auto name : exports) {
    if (wasm.getExportOrNull(name)) {
      // TODO: Fix error location
      return in.err("repeated export name");
    }
    wasm.addExport(Builder(wasm).makeExport(name, item->name, kind));
  }
  return Ok{};
}

} // anonymous namespace

Result<Function*>
ParseDeclsCtx::addFuncDecl(Index pos, Name name, ImportNames* importNames) {
  auto f = std::make_unique<Function>();
  if (name.is()) {
    if (wasm.getFunctionOrNull(name)) {
      // TDOO: if the existing function is not explicitly named, fix its name
      // and continue.
      return in.err(pos, "repeated function name");
    }
    f->setExplicitName(name);
  } else {
    name = (importNames ? "fimport$" : "") + std::to_string(funcCounter++);
    name = Names::getValidFunctionName(wasm, name);
    f->name = name;
  }
  applyImportNames(*f, importNames);
  return wasm.addFunction(std::move(f));
}

Result<> ParseDeclsCtx::addFunc(Name name,
                                const std::vector<Name>& exports,
                                ImportNames* import,
                                TypeUseT type,
                                std::optional<LocalsT>,
                                Index pos) {
  if (import && hasNonImport) {
    return in.err(pos, "import after non-import");
  }
  auto f = addFuncDecl(pos, name, import);
  CHECK_ERR(f);
  CHECK_ERR(addExports(in, wasm, *f, exports, ExternalKind::Function));
  funcDefs.push_back({name, pos, Index(funcDefs.size())});
  return Ok{};
}

Result<Memory*> ParseDeclsCtx::addMemoryDecl(Index pos,
                                             Name name,
                                             ImportNames* importNames,
                                             MemType type) {
  auto m = std::make_unique<Memory>();
  m->indexType = type.type;
  m->initial = type.limits.initial;
  m->max = type.limits.max;
  m->shared = type.shared;
  if (name) {
    // TODO: if the existing memory is not explicitly named, fix its name
    // and continue.
    if (wasm.getMemoryOrNull(name)) {
      return in.err(pos, "repeated memory name");
    }
    m->setExplicitName(name);
  } else {
    name = (importNames ? "mimport$" : "") + std::to_string(memoryCounter++);
    name = Names::getValidMemoryName(wasm, name);
    m->name = name;
  }
  applyImportNames(*m, importNames);
  return wasm.addMemory(std::move(m));
}

Result<> ParseDeclsCtx::addMemory(Name name,
                                  const std::vector<Name>& exports,
                                  ImportNames* import,
                                  MemType type,
                                  Index pos) {
  if (import && hasNonImport) {
    return in.err(pos, "import after non-import");
  }
  auto m = addMemoryDecl(pos, name, import, type);
  CHECK_ERR(m);
  CHECK_ERR(addExports(in, wasm, *m, exports, ExternalKind::Memory));
  memoryDefs.push_back({name, pos, Index(memoryDefs.size())});
  return Ok{};
}

Result<> ParseDeclsCtx::addImplicitData(DataStringT&& data) {
  auto& mem = *wasm.memories.back();
  auto d = std::make_unique<DataSegment>();
  d->memory = mem.name;
  d->isPassive = false;
  d->offset = Builder(wasm).makeConstPtr(0, mem.indexType);
  d->data = std::move(data);
  d->name = Names::getValidDataSegmentName(wasm, "implicit-data");
  wasm.addDataSegment(std::move(d));
  return Ok{};
}

Result<Global*>
ParseDeclsCtx::addGlobalDecl(Index pos, Name name, ImportNames* importNames) {
  auto g = std::make_unique<Global>();
  if (name) {
    if (wasm.getGlobalOrNull(name)) {
      // TODO: if the existing global is not explicitly named, fix its name
      // and continue.
      return in.err(pos, "repeated global name");
    }
    g->setExplicitName(name);
  } else {
    name = (importNames ? "gimport$" : "") + std::to_string(globalCounter++);
    name = Names::getValidGlobalName(wasm, name);
    g->name = name;
  }
  applyImportNames(*g, importNames);
  return wasm.addGlobal(std::move(g));
}

Result<> ParseDeclsCtx::addGlobal(Name name,
                                  const std::vector<Name>& exports,
                                  ImportNames* import,
                                  GlobalTypeT,
                                  std::optional<ExprT>,
                                  Index pos) {
  if (import && hasNonImport) {
    return in.err(pos, "import after non-import");
  }
  auto g = addGlobalDecl(pos, name, import);
  CHECK_ERR(g);
  CHECK_ERR(addExports(in, wasm, *g, exports, ExternalKind::Global));
  globalDefs.push_back({name, pos, Index(globalDefs.size())});
  return Ok{};
}

Result<> ParseDeclsCtx::addData(Name name,
                                MemoryIdxT*,
                                std::optional<ExprT>,
                                std::vector<char>&& data,
                                Index pos) {
  auto d = std::make_unique<DataSegment>();
  if (name) {
    if (wasm.getDataSegmentOrNull(name)) {
      // TODO: if the existing segment is not explicitly named, fix its name
      // and continue.
      return in.err(pos, "repeated data segment name");
    }
    d->setExplicitName(name);
  } else {
    name = std::to_string(dataCounter++);
    name = Names::getValidDataSegmentName(wasm, name);
    d->name = name;
  }
  d->data = std::move(data);
  dataDefs.push_back({name, pos, Index(wasm.dataSegments.size())});
  wasm.addDataSegment(std::move(d));
  return Ok{};
}

} // namespace wasm::WATParser
