// Copyright 2017-2022 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/flow_tree.h"

#include <map>
#include <string>
#include <vector>

#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "verilog/parser/verilog_token_enum.h"

namespace verilog {

// Adds edges within a conditonal block.
// Such that the first edge represents the condition being true,
// and the second edge represents the condition being false.
absl::Status FlowTree::AddBlockEdges(const ConditionalBlock &block) {
  bool contains_elsif = !block.elsif_locations.empty();
  bool contains_else = block.else_location != source_sequence_.end();

  // Handling `ifdef/ifndef.

  // Assuming the condition is true.
  edges_[block.if_location].push_back(block.if_location + 1);

  // Assuming the condition is false.
  // Checking if there is an `elsif.
  if (contains_elsif) {
    // Add edge to the first `elsif in the block.
    edges_[block.if_location].push_back(block.elsif_locations[0]);
  } else if (contains_else) {
    // Checking if there is an `else.
    edges_[block.if_location].push_back(block.else_location);
  } else {
    // `endif exists.
    edges_[block.if_location].push_back(block.endif_location);
  }

  // Handling `elsif.
  if (contains_elsif) {
    for (auto iter = block.elsif_locations.begin();
         iter != block.elsif_locations.end(); iter++) {
      // Assuming the condition is true.
      edges_[*iter].push_back((*iter) + 1);

      // Assuming the condition is false.
      if (iter + 1 != block.elsif_locations.end())
        edges_[*iter].push_back(*(iter + 1));
      else if (contains_else)
        edges_[*iter].push_back(block.else_location);
      else
        edges_[*iter].push_back(block.endif_location);
    }
  }

  // Handling `else.
  if (contains_else) {
    edges_[block.else_location].push_back(block.else_location + 1);
  }

  // For edges that are generated assuming the conditons are true,
  // We need to add an edge from the end of the condition group of lines to
  // `endif, e.g. `ifdef
  //    <line1>
  //    <line2>
  //    ...
  //    <line_final>
  // `else
  //    <group_of_lines>
  // `endif
  // Edge to be added: from <line_final> to `endif.
  edges_[block.endif_location - 1].push_back(block.endif_location);
  if (contains_elsif) {
    for (auto iter : block.elsif_locations)
      edges_[iter - 1].push_back(block.endif_location);
  }
  if (contains_else) {
    edges_[block.else_location - 1].push_back(block.endif_location);
  }

  // Connecting `endif to the next token directly (if not EOF).
  auto next_iter = block.endif_location + 1;
  if (next_iter != source_sequence_.end() &&
      next_iter->token_enum() != PP_else &&
      next_iter->token_enum() != PP_elsif &&
      next_iter->token_enum() != PP_endif) {
    edges_[block.endif_location].push_back(next_iter);
  }

  return absl::OkStatus();
}

// Checks if the iterator is pointing to a conditional directive.
bool FlowTree::IsConditional(TokenSequenceConstIterator iterator) {
  auto current_node = iterator->token_enum();
  return current_node == PP_ifndef || current_node == PP_ifdef ||
         current_node == PP_elsif || current_node == PP_else ||
         current_node == PP_endif;
}

// Checks if after the conditional_iterator (`ifdef/`ifndef... ) there exists
// a macro identifier.
absl::Status FlowTree::MacroFollows(
    TokenSequenceConstIterator conditional_iterator) {
  if (conditional_iterator->token_enum() != PP_ifdef &&
      conditional_iterator->token_enum() != PP_ifndef &&
      conditional_iterator->token_enum() != PP_elsif) {
    return absl::InvalidArgumentError("Error macro name can't be extracted.");
  }
  auto macro_iterator = conditional_iterator + 1;
  if (macro_iterator->token_enum() != PP_Identifier)
    return absl::InvalidArgumentError("Expected identifier for macro name.");
  else
    return absl::OkStatus();
}

// Adds a conditional macro to conditional_macros_ if not added before,
// And gives it a new ID, then saves the ID in conditional_macro_id_ map.
absl::Status FlowTree::AddMacroOfConditional(
    TokenSequenceConstIterator conditional_iterator) {
  auto status = MacroFollows(conditional_iterator);
  if (!status.ok()) {
    return absl::InvalidArgumentError(
        "Error no macro follows the conditional directive.");
  }
  auto macro_iterator = conditional_iterator + 1;
  auto macro_identifier = macro_iterator->text();
  if (conditional_macro_id_.find(macro_identifier) ==
      conditional_macro_id_.end()) {
    conditional_macro_id_[macro_identifier] = conditional_macros_counter_;
    conditional_macros_.push_back(macro_iterator);
    conditional_macros_counter_++;
  }
  return absl::OkStatus();
}

// Gets the conditonal macro ID from the conditional_macro_id_.
// Note: conditional_iterator is pointing to the conditional.
int FlowTree::GetMacroIDOfConditional(
    TokenSequenceConstIterator conditional_iterator) {
  auto status = MacroFollows(conditional_iterator);
  if (!status.ok()) {
    // TODO(karimtera): add a better error handling.
    return -1;
  }
  auto macro_iterator = conditional_iterator + 1;
  auto macro_identifier = macro_iterator->text();
  // It is always assumed that the macro already exists in the map.
  return conditional_macro_id_[macro_identifier];
}

// An API that provides a callback function to receive variants.
absl::Status FlowTree::GenerateVariants(const VariantReceiver &receiver) {
  auto status = GenerateControlFlowTree();
  if (!status.ok()) {
    return status;
  }
  return DepthFirstSearch(receiver, source_sequence_.begin());
}

// Constructs the control flow tree, which determines the edge from each node
// (token index) to the next possible childs, And save edge_from_iterator in
// edges_.
absl::Status FlowTree::GenerateControlFlowTree() {
  // Adding edges for if blocks.
  const TokenSequenceConstIterator non_location = source_sequence_.end();

  for (TokenSequenceConstIterator iter = source_sequence_.begin();
       iter != source_sequence_.end(); iter++) {
    int current_token_enum = iter->token_enum();

    if (IsConditional(iter)) {
      switch (current_token_enum) {
        case PP_ifdef:
        case PP_ifndef: {
          if_blocks_.emplace_back(iter, non_location);
          auto status = AddMacroOfConditional(iter);
          if (!status.ok()) {
            return absl::InvalidArgumentError(
                "ERROR: couldn't give a macro an ID.");
          }
          break;
        }
        case PP_elsif: {
          if (if_blocks_.empty()) {
            return absl::InvalidArgumentError("ERROR: Unmatched `elsif.");
          }
          if_blocks_.back().elsif_locations.push_back(iter);
          auto status = AddMacroOfConditional(iter);
          if (!status.ok()) {
            return absl::InvalidArgumentError(
                "ERROR: couldn't give a macro an ID.");
          }
          break;
        }
        case PP_else: {
          if (if_blocks_.empty()) {
            return absl::InvalidArgumentError("ERROR: Unmatched `else.");
          }
          if_blocks_.back().else_location = iter;
          break;
        }
        case PP_endif: {
          if (if_blocks_.empty()) {
            return absl::InvalidArgumentError("ERROR: Unmatched `endif.");
          }
          if_blocks_.back().endif_location = iter;
          auto status = AddBlockEdges(if_blocks_.back());
          if (!status.ok()) return status;
          // TODO(karimtera): add an error message.
          if_blocks_.pop_back();
          break;
        }
      }

    } else {
      // Only add normal edges if the next token is not `else/`elsif/`endif.
      auto next_iter = iter + 1;
      if (next_iter != source_sequence_.end() &&
          next_iter->token_enum() != PP_else &&
          next_iter->token_enum() != PP_elsif &&
          next_iter->token_enum() != PP_endif) {
        edges_[iter].push_back(next_iter);
      }
    }
  }

  // Checks for uncompleted conditionals.
  if (!if_blocks_.empty())
    return absl::InvalidArgumentError(
        "ERROR: Uncompleted conditional is found.");

  return absl::OkStatus();
}

// Traveses the control flow tree in a depth first manner, appending the visited
// tokens to current_variant_, then provide the completed variant to the user
// using a callback function (VariantReceiver).
absl::Status FlowTree::DepthFirstSearch(
    const VariantReceiver &receiver, TokenSequenceConstIterator current_node) {
  if (!wants_more_) return absl::OkStatus();

  // Skips directives so that current_variant_ doesn't contain any.
  if (current_node->token_enum() != PP_Identifier &&
      current_node->token_enum() != PP_ifndef &&
      current_node->token_enum() != PP_ifdef &&
      current_node->token_enum() != PP_define &&
      current_node->token_enum() != PP_define_body &&
      current_node->token_enum() != PP_elsif &&
      current_node->token_enum() != PP_else &&
      current_node->token_enum() != PP_endif) {
    current_variant_.sequence.push_back(*current_node);
  }

  // Checks if the current token is a `ifdef/`ifndef/`elsif.
  if (current_node->token_enum() == PP_ifdef ||
      current_node->token_enum() == PP_ifndef ||
      current_node->token_enum() == PP_elsif) {
    int macro_id = GetMacroIDOfConditional(current_node);
    bool negated = (current_node->token_enum() == PP_ifndef);
    // Checks if this macro is already visited (either defined/undefined).
    if (current_variant_.visited.test(macro_id)) {
      bool assume_condition_is_true =
          (negated ^ current_variant_.macros_mask.test(macro_id));
      if (auto status = DepthFirstSearch(
              receiver, edges_[current_node][!assume_condition_is_true]);
          !status.ok()) {
        std::cerr << "ERROR: DepthFirstSearch fails.";
        return status;
      }
    } else {
      current_variant_.visited.flip(macro_id);
      // This macro wans't visited before, then we can check both edges.
      // Assume the condition is true.
      if (negated)
        current_variant_.macros_mask.reset(macro_id);
      else
        current_variant_.macros_mask.set(macro_id);
      if (auto status = DepthFirstSearch(receiver, edges_[current_node][0]);
          !status.ok()) {
        std::cerr << "ERROR: DepthFirstSearch fails.";
        return status;
      }

      // Assume the condition is false.
      if (!negated)
        current_variant_.macros_mask.reset(macro_id);
      else
        current_variant_.macros_mask.set(macro_id);
      if (auto status = DepthFirstSearch(receiver, edges_[current_node][1]);
          !status.ok()) {
        std::cerr << "ERROR: DepthFirstSearch fails.";
        return status;
      }
      // Undo the change to allow for backtracking.
      current_variant_.visited.flip(macro_id);
    }
  } else {
    // Do recursive search through every possible edge.
    // Expected to be only one edge in this case.
    for (auto next_node : edges_[current_node]) {
      if (auto status = FlowTree::DepthFirstSearch(receiver, next_node);
          !status.ok()) {
        std::cerr << "ERROR: DepthFirstSearch fails\n";
        return status;
      }
    }
  }
  // If the current node is the last one, push the completed current_variant_
  // then it is ready to be sent.
  if (current_node == source_sequence_.end() - 1) {
    wants_more_ &= receiver(current_variant_);
  }
  if (current_node->token_enum() != PP_Identifier &&
      current_node->token_enum() != PP_ifndef &&
      current_node->token_enum() != PP_ifdef &&
      current_node->token_enum() != PP_define &&
      current_node->token_enum() != PP_define_body &&
      current_node->token_enum() != PP_elsif &&
      current_node->token_enum() != PP_else &&
      current_node->token_enum() != PP_endif) {
    // Remove tokens to back track into other variants.
    current_variant_.sequence.pop_back();
  }
  return absl::OkStatus();
}

}  // namespace verilog
