// Copyright 2017-2020 The Verible Authors.
//
// 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 "verilog/CST/module.h"

#include <vector>

#include "common/analysis/matcher/matcher.h"
#include "common/analysis/matcher/matcher_builders.h"
#include "common/analysis/syntax_tree_search.h"
#include "common/text/concrete_syntax_leaf.h"
#include "common/text/concrete_syntax_tree.h"
#include "common/text/symbol.h"
#include "common/text/token_info.h"
#include "common/text/tree_utils.h"
#include "verilog/CST/verilog_matchers.h"  // IWYU pragma: keep

namespace verilog {

using verible::Symbol;
using verible::SyntaxTreeNode;
using verible::TokenInfo;

std::vector<verible::TreeSearchMatch> FindAllModuleDeclarations(
    const Symbol &root) {
  return SearchSyntaxTree(root, NodekModuleDeclaration());
}

std::vector<verible::TreeSearchMatch> FindAllModuleHeaders(const Symbol &root) {
  return SearchSyntaxTree(root, NodekModuleHeader());
}

std::vector<verible::TreeSearchMatch> FindAllInterfaceDeclarations(
    const verible::Symbol &root) {
  return SearchSyntaxTree(root, NodekInterfaceDeclaration());
}

std::vector<verible::TreeSearchMatch> FindAllProgramDeclarations(
    const verible::Symbol &root) {
  return SearchSyntaxTree(root, NodekProgramDeclaration());
}

bool IsModuleOrInterfaceOrProgramDeclaration(
    const SyntaxTreeNode &declaration) {
  return declaration.MatchesTagAnyOf({NodeEnum::kModuleDeclaration,
                                      NodeEnum::kInterfaceDeclaration,
                                      NodeEnum::kProgramDeclaration});
}

const SyntaxTreeNode *GetModuleHeader(const Symbol &module_declaration) {
  if (module_declaration.Kind() != verible::SymbolKind::kNode) return nullptr;
  const SyntaxTreeNode &module_node =
      verible::SymbolCastToNode(module_declaration);
  if (!IsModuleOrInterfaceOrProgramDeclaration(module_node)) return nullptr;
  if (module_node.empty()) return nullptr;
  return &verible::SymbolCastToNode(*module_node[0].get());
}

const SyntaxTreeNode *GetInterfaceHeader(const Symbol &module_symbol) {
  return verible::GetSubtreeAsNode(module_symbol,
                                   NodeEnum::kInterfaceDeclaration, 0,
                                   NodeEnum::kModuleHeader);
}

const verible::SyntaxTreeLeaf *GetModuleName(const Symbol &s) {
  const auto *header_node = GetModuleHeader(s);
  if (!header_node) return nullptr;
  return verible::GetSubtreeAsLeaf(*header_node, NodeEnum::kModuleHeader, 2);
}

const TokenInfo *GetInterfaceNameToken(const Symbol &s) {
  const auto *header_node = GetInterfaceHeader(s);
  if (!header_node) return nullptr;
  const verible::SyntaxTreeLeaf *name_leaf =
      verible::GetSubtreeAsLeaf(*header_node, NodeEnum::kModuleHeader, 2);
  return name_leaf ? &name_leaf->get() : nullptr;
}

const SyntaxTreeNode *GetModulePortParenGroup(
    const Symbol &module_declaration) {
  const auto *header_node = GetModuleHeader(module_declaration);
  if (!header_node) return nullptr;
  const auto *ports =
      verible::GetSubtreeAsSymbol(*header_node, NodeEnum::kModuleHeader, 5);
  return verible::CheckOptionalSymbolAsNode(ports, NodeEnum::kParenGroup);
}

const SyntaxTreeNode *GetModulePortDeclarationList(
    const Symbol &module_declaration) {
  const auto *paren_group = GetModulePortParenGroup(module_declaration);
  if (verible::CheckOptionalSymbolAsNode(paren_group, NodeEnum::kParenGroup) ==
      nullptr) {
    return nullptr;
  }
  return verible::GetSubtreeAsNode(*paren_group, NodeEnum::kParenGroup, 1,
                                   NodeEnum::kPortDeclarationList);
}

const verible::SyntaxTreeLeaf *GetModuleEndLabel(
    const verible::Symbol &module_declaration) {
  const SyntaxTreeNode &module_node =
      verible::SymbolCastToNode(module_declaration);
  CHECK(IsModuleOrInterfaceOrProgramDeclaration(module_node));

  const auto *label_node = module_node[3].get();
  if (label_node == nullptr) {
    return nullptr;
  }
  return verible::GetSubtreeAsLeaf(verible::SymbolCastToNode(*label_node),
                                   NodeEnum::kLabel, 1);
}

const verible::SyntaxTreeNode *GetModuleItemList(
    const verible::Symbol &module_declaration) {
  if (module_declaration.Kind() != verible::SymbolKind::kNode) return nullptr;
  const SyntaxTreeNode &module_node =
      verible::SymbolCastToNode(module_declaration);
  if (!IsModuleOrInterfaceOrProgramDeclaration(module_node)) return nullptr;
  if (module_node.size() < 2) return nullptr;
  verible::Symbol *item = module_node[1].get();
  return item ? &verible::SymbolCastToNode(*item) : nullptr;
}

const verible::SyntaxTreeNode *GetParamDeclarationListFromModuleDeclaration(
    const verible::Symbol &module_declaration) {
  const auto *header_node = GetModuleHeader(module_declaration);
  if (!header_node) return nullptr;
  const verible::Symbol *param_declaration_list =
      verible::GetSubtreeAsSymbol(*header_node, NodeEnum::kModuleHeader, 4);
  return verible::CheckOptionalSymbolAsNode(
      param_declaration_list, NodeEnum::kFormalParameterListDeclaration);
}

const verible::SyntaxTreeNode *GetParamDeclarationListFromInterfaceDeclaration(
    const verible::Symbol &interface_declaration) {
  const auto *header_node = GetInterfaceHeader(interface_declaration);
  if (!header_node) return nullptr;
  const verible::Symbol *param_declaration_list =
      verible::GetSubtreeAsSymbol(*header_node, NodeEnum::kModuleHeader, 4);
  return verible::CheckOptionalSymbolAsNode(
      param_declaration_list, NodeEnum::kFormalParameterListDeclaration);
}

}  // namespace verilog
