// 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 "common/formatting/tree_unwrapper.h"

#include <functional>
#include <iterator>
#include <memory>
#include <ostream>
#include <vector>

#include "common/formatting/format_token.h"
#include "common/formatting/token_partition_tree.h"
#include "common/formatting/unwrapped_line.h"
#include "common/text/concrete_syntax_tree.h"
#include "common/text/symbol.h"
#include "common/text/syntax_tree_context.h"
#include "common/text/text_structure.h"
#include "common/text/token_info.h"
#include "common/text/token_stream_view.h"
#include "common/util/logging.h"
#include "common/util/tree_operations.h"
#include "common/util/value_saver.h"
#include "common/util/vector_tree.h"

namespace verible {

void TreeUnwrapper::VerifyFullTreeFormatTokenRanges() const {
  verible::VerifyFullTreeFormatTokenRanges(unwrapped_lines_,
                                           preformatted_tokens_.begin());
}

static TokenPartitionTree MakeInitialUnwrappedLines(
    int indentation, FormatTokenRange::const_iterator first_token) {
  // Root node spanning the entire file
  auto unwrapped_lines = TokenPartitionTree(UnwrappedLine(
      indentation, first_token, PartitionPolicyEnum::kAlwaysExpand));
  // First unwrapped line
  unwrapped_lines.Children().emplace_back(UnwrappedLine(
      indentation, first_token
      // TODO(fangism): set partition policy here?
      ));
  return unwrapped_lines;
}

TreeUnwrapper::TreeUnwrapper(
    const TextStructureView& view,
    const preformatted_tokens_type& preformatted_tokens)
    : text_structure_view_(view),
      preformatted_tokens_(preformatted_tokens),
      next_unfiltered_token_(text_structure_view_.TokenStream().begin()),
      unwrapped_lines_(MakeInitialUnwrappedLines(current_indentation_spaces_,
                                                 preformatted_tokens_.begin())),
      // The "top-most" UnwrappedLine spans the entire file, so the first
      // unwrapped line should be a considered a partition (child) thereof.
      // This acts like 'pushing' the first child onto a stack.
      active_unwrapped_lines_(&unwrapped_lines_.Children().front()) {
  // Every new unwrapped line will be initially empty, but the range
  // will point to the correct starting position in the preformatted_tokens_
  // array, and be able to 'extend' into the array of preformatted_tokens_.
}

const TokenPartitionTree* TreeUnwrapper::Unwrap() {
  // Collect tokens that appear before first syntax tree leaf, e.g. comments.
  CollectLeadingFilteredTokens();

  // Traverse the concrete syntax tree to build up token partitions.
  ABSL_DIE_IF_NULL(text_structure_view_.SyntaxTree())->Accept(this);

  // After traversing the ConcreteSyntaxTree, collect possible tokens filtered
  // after the right-most leaf until the end-of-file.
  CollectTrailingFilteredTokens();

  // No action needed to close out the most recent UnwrappedLine.
  if (!preformatted_tokens_.empty()) {
    const auto iter = CurrentFormatTokenIterator() - 1;
    const auto back = preformatted_tokens_.end() - 1;
    // Ensure that we have spanned the last significant token (used for
    // formatting).  It is possible that unfiltered tokens include trailing
    // newlines after the last leaf, which is why the iterators may not
    // necessarily line up exactly.
    CHECK(iter >= back) << "missing " << std::distance(iter, back)
                        << " format tokens at the end.  got: " << *iter->token
                        << " vs. " << *back->token;
  }

  {
    // This 'pops' the tree node stack once more to balance the initial
    // child 'push' that was done in the constructor's initialization
    // of active_unwrapped_lines_.
    active_unwrapped_lines_ = active_unwrapped_lines_->Parent();
    // Confirm that tree visitation is balanced.
    CHECK_EQ(active_unwrapped_lines_, &unwrapped_lines_);
    FinishUnwrappedLine();
  }

  VerifyFullTreeFormatTokenRanges();

  return &unwrapped_lines_;
}

std::vector<UnwrappedLine> TreeUnwrapper::FullyPartitionedUnwrappedLines()
    const {
  // If a node of the ExpandedTree<UnwrappedLine> has children,
  // visit only the node's children.
  std::vector<UnwrappedLine> result;
  verible::ApplyPostOrder(unwrapped_lines_,
                          [&result](const TokenPartitionTree& node) {
                            if (is_leaf(node)) {
                              result.push_back(node.Value());
                            }
                          });

  // Filter out trailing blank UnwrappedLines.
  while (!result.empty() && result.back().IsEmpty()) {
    result.pop_back();
  }
  return result;
}

TokenSequence::const_iterator TreeUnwrapper::NextUnfilteredToken() const {
  const auto& origin_tokens = text_structure_view_.TokenStream();
  CHECK(next_unfiltered_token_ >= origin_tokens.begin());
  CHECK(next_unfiltered_token_ <= origin_tokens.end());
  return next_unfiltered_token_;
}

TreeUnwrapper::preformatted_tokens_type::const_iterator
TreeUnwrapper::CurrentFormatTokenIterator() const {
  // Caution to caller: this could return preformatted_tokens_.end()
  return CurrentUnwrappedLine().TokensRange().end();
}

UnwrappedLine& TreeUnwrapper::CurrentUnwrappedLine() {
  return ABSL_DIE_IF_NULL(CurrentTokenPartition())->Value();
}

const UnwrappedLine& TreeUnwrapper::CurrentUnwrappedLine() const {
  return ABSL_DIE_IF_NULL(CurrentTokenPartition())->Value();
}

void TreeUnwrapper::RemoveTrailingEmptyPartitions(TokenPartitionTree* node) {
  auto& children = node->Children();
  while (!children.empty() && children.back().Value().IsEmpty()) {
    children.pop_back();
  }
}

void TreeUnwrapper::CloseUnwrappedLineTreeNode(
    TokenPartitionTree* node,
    preformatted_tokens_type::const_iterator token_iter) {
  const auto& children = node->Children();
  if (!children.empty()) {
    const auto last_child_end = children.back().Value().TokensRange().end();
    CHECK(last_child_end >= token_iter)
        << "Child range should never have to catch up to parent.";
    if (token_iter < last_child_end) {
      // Parent needs to catch up to child.
      // This can occur because we're only updating one active_unwrapped_line_
      // node at a time, so this is needed to maintain the parent-child
      // range equivalence.
      node->Value().SpanUpToToken(last_child_end);
    }
  }
}

void TreeUnwrapper::FinishUnwrappedLine() {
  RemoveTrailingEmptyPartitions(active_unwrapped_lines_);

  const auto iter = CurrentFormatTokenIterator();
  CloseUnwrappedLineTreeNode(active_unwrapped_lines_, iter);

  // At this point, the current active_unwrapped_lines_ is finalized because
  // we are starting a new one.  Now is the right time to verify invariants.
  VerifyTreeNodeFormatTokenRanges(*active_unwrapped_lines_,
                                  preformatted_tokens_.begin());
}

void TreeUnwrapper::StartNewUnwrappedLine(PartitionPolicyEnum partitioning,
                                          const Symbol* origin) {
  // TODO(fangism): Take an optional indentation depth override parameter.
  auto& current_unwrapped_line = CurrentUnwrappedLine();
  if (current_unwrapped_line.IsEmpty()) {  // token range is empty
    // Re-use previously created unwrapped line.
    current_unwrapped_line.SetIndentationSpaces(current_indentation_spaces_);
    current_unwrapped_line.SetPartitionPolicy(partitioning);
    current_unwrapped_line.SetOrigin(origin);
    VLOG(4) << "re-using node at " << NodePath(*active_unwrapped_lines_) << ": "
            << current_unwrapped_line;
    // There may have been subtrees created with empty ranges, e.g.
    // for the sake of being able to correctly indent comments inside blocks.
    // If so, delete those so that token partition range invariants are
    // maintained through re-use of an existing node.
    if (!is_leaf(*active_unwrapped_lines_)) {
      VLOG(4) << "removed pre-existing child partitions.";
      active_unwrapped_lines_->Children().clear();
    }
  } else {
    // To maintain the invariant that a parent range's upper-bound is equal
    // to the upper-bound of its last child, we may have to add one more
    // child whose range spans up to the parent's upper-bound.
    // The right time to do this is when an UnwrappedLine is finalized,
    // which is the same time that a new UnwrappedLine is added, here.
    FinishUnwrappedLine();

    // Create new sibling to current unwrapped line, maintaining same level.
    auto& siblings = active_unwrapped_lines_->Parent()->Children();
    siblings.emplace_back(UnwrappedLine(current_indentation_spaces_,
                                        CurrentFormatTokenIterator(),
                                        partitioning));
    active_unwrapped_lines_ = &siblings.back();
    CurrentUnwrappedLine().SetOrigin(origin);
    VLOG(4) << "new sibling node " << NodePath(*active_unwrapped_lines_) << ": "
            << CurrentUnwrappedLine();
  }
}

void TreeUnwrapper::AddTokenToCurrentUnwrappedLine() {
  CHECK(NextUnfilteredTokenIsRetained());
  // Advance CurrentFormatTokenIterator().
  CurrentUnwrappedLine().SpanNextToken();
  VLOG(4) << "appended: " << *CurrentUnwrappedLine().TokensRange().back().token;
  ++next_unfiltered_token_;
}

bool TreeUnwrapper::NextUnfilteredTokenIsRetained() const {
  const auto iter = CurrentFormatTokenIterator();
  // (iter->token == &*next_unfiltered_token_) implies that is was one of the
  // tokens preserved in the subset array of filtered tokens, as determined
  // by a predication function (keeper), but without having to re-check
  // (and maintain a copy/reference of) the keeper predicate, nor perform
  // a set membership check (e.g. binary search).
  // This works only because we maintain that next_unfiltered_token_
  // will never lead nor lag CurrentFormatTokenIterator() by more than one
  // filtered token.
  return iter != preformatted_tokens_.end() &&  // possible if array is empty
         iter->token == &*next_unfiltered_token_;
}

void TreeUnwrapper::SkipUnfilteredTokens(
    const std::function<bool(const verible::TokenInfo&)>& predicate) {
  while (predicate(*next_unfiltered_token_)) {
    ++next_unfiltered_token_;
  }
}

// Advances next_unfiltered_token_ and also places the token into the
// CurrentUnwrappedLine() if it is a non-whitespace token, like a comment.
void TreeUnwrapper::AdvanceNextUnfilteredToken() {
  if (next_unfiltered_token_->isEOF()) return;
  if (NextUnfilteredTokenIsRetained()) {
    // This is a non-syntax-tree token, such as a comment or attribute.
    // Based on the KeepNonWhitespace predicate, next_unfiltered_token_
    // must point to the next PreFormatToken.
    // This already advances next_unfiltered_token_.
    AddTokenToCurrentUnwrappedLine();
  } else {
    // The inverse condition implies that the token pointed to was filtered
    // out, e.g. whitespace.
    ++next_unfiltered_token_;
  }
}

void TreeUnwrapper::TraverseChildren(const verible::SyntaxTreeNode& node) {
  // Can't just use TreeContextVisitor::Visit(node) because we need to
  // call a visit hook between children.
  const verible::SyntaxTreeContext::AutoPop p(&current_context_, &node);
  InterChildNodeHook(node);
  for (const auto& child : node.children()) {
    if (child) {
      child->Accept(this);
      InterChildNodeHook(node);
    }
  }
}

TreeUnwrapper::preformatted_tokens_type::const_iterator
TreeUnwrapper::VisitIndentedChildren(const SyntaxTreeNode& node,
                                     int indentation_delta,
                                     PartitionPolicyEnum partitioning) {
  // Visit subtree with increased indentation level.
  const ValueSaver<int> depth_saver(
      &current_indentation_spaces_,
      current_indentation_spaces_ + indentation_delta);

  // Mark a new sibling at the new indentation level, apply partition policy.
  StartNewUnwrappedLine(partitioning, &node);

  // Start first child right away.
  active_unwrapped_lines_->Children().emplace_back(
      UnwrappedLine(current_indentation_spaces_, CurrentFormatTokenIterator(),
                    PartitionPolicyEnum::kFitOnLineElseExpand /* default */));
  const ValueSaver<TokenPartitionTree*> tree_saver(
      &active_unwrapped_lines_, &active_unwrapped_lines_->Children().back());
  VLOG(3) << __FUNCTION__ << ", new child node "
          << NodePath(*active_unwrapped_lines_) << ": "
          << CurrentUnwrappedLine();
  TraverseChildren(node);

  return CurrentFormatTokenIterator();

  // To maintain the invariant that a parent range's upper-bound is equal
  // to the upper-bound of its last child, we may have to add one more
  // child whose range spans up to the parent's upper-bound.
  // The right time to do this is when an UnwrappedLine is finalized,
  // which is the same time that a new UnwrappedLine is added.
  // See StartNewUnwrappedLine().
}

void TreeUnwrapper::VisitIndentedSection(const SyntaxTreeNode& node,
                                         int indentation_delta,
                                         PartitionPolicyEnum partitioning) {
  const auto last_ftoken_iter =
      VisitIndentedChildren(node, indentation_delta, partitioning);

  // TODO(fangism): do we ever need to remove trailing empty partitions here?

  // Update parent's end() format token iterator to match that of
  // its last child.  It can still be advanced later.
  active_unwrapped_lines_->Value().SpanUpToToken(last_ftoken_iter);

  // Start new empty UnwrappedLine at the previous indentation level.
  StartNewUnwrappedLine(PartitionPolicyEnum::kUninitialized, nullptr);
}

std::ostream& operator<<(std::ostream& stream, const TreeUnwrapper& unwrapper) {
  for (const auto& uwline : unwrapper.FullyPartitionedUnwrappedLines()) {
    stream << uwline << std::endl;
  }
  return stream;
}

}  // namespace verible
