// 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/analysis/dependencies.h"

#include <iostream>

#include "common/strings/compare.h"
#include "common/strings/display_utils.h"
#include "common/util/logging.h"
#include "verilog/analysis/symbol_table.h"
#include "verilog/analysis/verilog_project.h"

namespace verilog {

static FileDependencies::symbol_index_type CreateSymbolMapFromSymbolTable(
    const SymbolTableNode& root, const VerilogProject* project) {
  VLOG(1) << __FUNCTION__ << ": collecting definitions";
  CHECK(project != nullptr)
      << "VerilogProject* is required for dependency analysis.";
  FileDependencies::symbol_index_type symbols_index;

  using SymbolData = FileDependencies::SymbolData;

  // Collect definers of root-level symbols.
  for (const SymbolTableNode::key_value_type& child : root) {
    const absl::string_view symbol_name(child.first);
    const VerilogSourceFile* file_origin = child.second.Value().file_origin;
    if (file_origin == nullptr) continue;

    SymbolData& symbol_data(symbols_index[symbol_name]);
    if (symbol_data.definer == nullptr) {
      // Take the first definition, arbitrarily.
      symbol_data.definer = file_origin;
    }
  }

  // Collect all unqualified and unresolved references from all scopes.
  VLOG(1) << __FUNCTION__ << ": collecting references";
  root.ApplyPreOrder([&symbols_index, project](const SymbolTableNode& node) {
    const SymbolInfo& symbol_info(node.Value());
    for (const DependentReferences& ref :
         symbol_info.local_references_to_bind) {
      // Only look at the root reference node, which is unqualified.
      const ReferenceComponent& ref_comp(ref.components->Value());
      const absl::string_view ref_id(ref_comp.identifier);
      VLOG(2) << "  referenced id: " << ref_id;

      const VerilogSourceFile* ref_file_origin =
          project->LookupFileOrigin(ref_id);
      if (ref_file_origin == nullptr) continue;  // unknown file

      if (ref_comp.resolved_symbol != nullptr) {
        const VerilogSourceFile* def_file_origin =
            ref_comp.resolved_symbol->Value().file_origin;
        if (ref_file_origin == def_file_origin) {
          continue;  // skip already resolved symbols in same file
        }
      }

      VLOG(2) << "  registering reference edge";
      SymbolData& symbol_data(symbols_index[ref_id]);
      symbol_data.referencers.insert(ref_file_origin);
    }
  });
  VLOG(1) << "end of " << __FUNCTION__;
  return symbols_index;  // move
}

// Struct for printing readable dependency edge.
struct DepEdge {
  const VerilogSourceFile* const ref;
  const VerilogSourceFile* const def;
  const FileDependencies::SymbolNameSet& symbols;
};

static std::ostream& operator<<(std::ostream& stream, const DepEdge& dep) {
  return stream << '"' << dep.ref->ReferencedPath() << "\" depends on \""
                << dep.def->ReferencedPath() << "\" for symbols "
                << verible::SequenceFormatter(dep.symbols, ", ", "{ ", " }");
}

static FileDependencies::file_deps_graph_type
CreateFileDependenciesFromSymbolMap(
    const FileDependencies::symbol_index_type& symbol_map) {
  VLOG(1) << __FUNCTION__;
  FileDependencies::file_deps_graph_type file_deps;
  for (const auto& symbol_entry : symbol_map) {
    const absl::string_view symbol_name(symbol_entry.first);
    const FileDependencies::SymbolData& symbol_info(symbol_entry.second);
    const VerilogSourceFile* def = symbol_info.definer;
    // If no definition is found, then do not create any edges for it.
    if (def == nullptr) continue;

    for (const VerilogSourceFile* ref : symbol_info.referencers) {
      // Skip self-edges.
      if (ref == def) continue;
      VLOG(2) << DepEdge{.ref = ref, .def = def, .symbols = {symbol_name}};
      file_deps[ref][def].insert(symbol_name);
    }
  }
  VLOG(1) << "end of " << __FUNCTION__;
  return file_deps;  // move
}

FileDependencies::FileDependencies(const SymbolTable& symbol_table)
    : root_symbols_index(CreateSymbolMapFromSymbolTable(
          symbol_table.Root(), symbol_table.Project())),
      file_deps(CreateFileDependenciesFromSymbolMap(root_symbols_index)) {
  // All the work is done by the initializers.
}

bool FileDependencies::Empty() const {
  for (const auto& ref : file_deps) {
    for (const auto& def : ref.second) {
      if (!def.second.empty()) return false;
    }
  }
  return true;
}

void FileDependencies::TraverseDependencyEdges(
    const std::function<void(const node_type&, const node_type&,
                             const SymbolNameSet&)>& edge_func) const {
  for (const auto& tail : file_deps) {
    for (const auto& head : tail.second) {
      edge_func(tail.first, head.first, head.second);
    }
  }
}

std::ostream& FileDependencies::PrintGraph(std::ostream& stream) const {
  TraverseDependencyEdges([&stream](const node_type& ref, const node_type& def,
                                    const SymbolNameSet& symbols) {
    stream << DepEdge{.ref = ref, .def = def, .symbols = symbols} << std::endl;
  });
  return stream;
}

std::ostream& operator<<(std::ostream& stream, const FileDependencies& deps) {
  return deps.PrintGraph(stream);
}

}  // namespace verilog
