/*
 * 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(Lexer& 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>,
                                std::vector<Annotation>&& annotations,
                                Index pos) {
  CHECK_ERR(checkImport(pos, 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()), std::move(annotations)});
  return Ok{};
}

Result<Table*> ParseDeclsCtx::addTableDecl(Index pos,
                                           Name name,
                                           ImportNames* importNames,
                                           TableType type) {
  auto t = std::make_unique<Table>();
  t->addressType = type.addressType;
  t->initial = type.limits.initial;
  t->max = type.limits.max ? *type.limits.max : Table::kUnlimitedSize;
  if (name.is()) {
    if (wasm.getTableOrNull(name)) {
      // TODO: if the existing table is not explicitly named, fix its name and
      // continue.
      return in.err(pos, "repeated table name");
    }
    t->setExplicitName(name);
  } else {
    name = (importNames ? "timport$" : "") + std::to_string(tableCounter++);
    name = Names::getValidTableName(wasm, name);
    t->name = name;
  }
  applyImportNames(*t, importNames);
  return wasm.addTable(std::move(t));
}

Result<> ParseDeclsCtx::addTable(Name name,
                                 const std::vector<Name>& exports,
                                 ImportNames* import,
                                 TableType type,
                                 Index pos) {
  CHECK_ERR(checkImport(pos, import));
  auto t = addTableDecl(pos, name, import, type);
  CHECK_ERR(t);
  CHECK_ERR(addExports(in, wasm, *t, exports, ExternalKind::Table));
  // TODO: table annotations
  tableDefs.push_back({name, pos, Index(tableDefs.size()), {}});
  return Ok{};
}

Result<> ParseDeclsCtx::addImplicitElems(TypeT, ElemListT&& elems) {
  auto& table = *wasm.tables.back();
  auto e = std::make_unique<ElementSegment>();
  e->table = table.name;
  e->offset = Builder(wasm).makeConstPtr(0, Type::i32);
  e->name = Names::getValidElementSegmentName(wasm, "implicit-elem");
  wasm.addElementSegment(std::move(e));

  // Record the index mapping so we can find this segment again to set its type
  // and elements in later phases.
  Index tableIndex = wasm.tables.size() - 1;
  Index elemIndex = wasm.elementSegments.size() - 1;
  implicitElemIndices[tableIndex] = elemIndex;

  return Ok{};
}

Result<Memory*> ParseDeclsCtx::addMemoryDecl(Index pos,
                                             Name name,
                                             ImportNames* importNames,
                                             MemType type) {
  auto m = std::make_unique<Memory>();
  m->addressType = type.addressType;
  m->initial = type.limits.initial;
  m->max = type.limits.max ? *type.limits.max : Memory::kUnlimitedSize;
  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) {
  CHECK_ERR(checkImport(pos, import));
  auto m = addMemoryDecl(pos, name, import, type);
  CHECK_ERR(m);
  CHECK_ERR(addExports(in, wasm, *m, exports, ExternalKind::Memory));
  // TODO: memory annotations
  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.addressType);
  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$" : "global$") + 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) {
  CHECK_ERR(checkImport(pos, import));
  auto g = addGlobalDecl(pos, name, import);
  CHECK_ERR(g);
  CHECK_ERR(addExports(in, wasm, *g, exports, ExternalKind::Global));
  // TODO: global annotations
  globalDefs.push_back({name, pos, Index(globalDefs.size()), {}});
  return Ok{};
}

Result<> ParseDeclsCtx::addElem(
  Name name, TableIdxT*, std::optional<ExprT>, ElemListT&&, Index pos) {
  auto e = std::make_unique<ElementSegment>();
  if (name) {
    if (wasm.getElementSegmentOrNull(name)) {
      // TDOO: if the existing segment is not explicitly named, fix its name and
      // continue.
      return in.err(pos, "repeated element segment name");
    }
    e->setExplicitName(name);
  } else {
    name = std::to_string(elemCounter++);
    name = Names::getValidElementSegmentName(wasm, name);
    e->name = name;
  }
  // TODO: element segment annotations
  elemDefs.push_back({name, pos, Index(wasm.elementSegments.size()), {}});
  wasm.addElementSegment(std::move(e));
  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);
  // TODO: data segment annotations
  dataDefs.push_back({name, pos, Index(wasm.dataSegments.size()), {}});
  wasm.addDataSegment(std::move(d));
  return Ok{};
}

Result<Tag*>
ParseDeclsCtx::addTagDecl(Index pos, Name name, ImportNames* importNames) {
  auto t = std::make_unique<Tag>();
  if (name) {
    if (wasm.getTagOrNull(name)) {
      // TODO: if the existing tag is not explicitly named, fix its name and
      // continue.
      return in.err(pos, "repeated tag name");
    }
    t->setExplicitName(name);
  } else {
    name = (importNames ? "eimport$" : "tag$") + std::to_string(tagCounter++);
    name = Names::getValidTagName(wasm, name);
    t->name = name;
  }
  applyImportNames(*t, importNames);
  return wasm.addTag(std::move(t));
}

Result<> ParseDeclsCtx::addTag(Name name,
                               const std::vector<Name>& exports,
                               ImportNames* import,
                               TypeUseT type,
                               Index pos) {
  CHECK_ERR(checkImport(pos, import));
  auto t = addTagDecl(pos, name, import);
  CHECK_ERR(t);
  CHECK_ERR(addExports(in, wasm, *t, exports, ExternalKind::Tag));
  // TODO: tag annotations
  tagDefs.push_back({name, pos, Index(tagDefs.size()), {}});
  return Ok{};
}

} // namespace wasm::WATParser
