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

#include <algorithm>
#include <iostream>
#include <iterator>
#include <map>
#include <sstream>
#include <string>
#include <vector>

#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "common/formatting/format_token.h"
#include "common/strings/display_utils.h"
#include "common/text/tree_utils.h"
#include "common/util/container_iterator_range.h"
#include "common/util/spacer.h"

namespace verible {

std::ostream& operator<<(std::ostream& stream, PartitionPolicyEnum p) {
  switch (p) {
    case PartitionPolicyEnum::kUninitialized:
      return stream << "uninitialized";
    case PartitionPolicyEnum::kAlwaysExpand:
      return stream << "always-expand";
    case PartitionPolicyEnum::kFitOnLineElseExpand:
      return stream << "fit-else-expand";
    case PartitionPolicyEnum::kTabularAlignment:
      return stream << "tabular-alignment";
    case PartitionPolicyEnum::kAlreadyFormatted:
      return stream << "already-formatted";
    case PartitionPolicyEnum::kInline:
      return stream << "inline";
    case PartitionPolicyEnum::kAppendFittingSubPartitions:
      return stream << "append-fitting-sub-partitions";
    case PartitionPolicyEnum::kJuxtaposition:
      return stream << "juxtaposition";
    case PartitionPolicyEnum::kStack:
      return stream << "stack";
    case PartitionPolicyEnum::kWrap:
      return stream << "wrap";
    case PartitionPolicyEnum::kJuxtapositionOrIndentedStack:
      return stream << "juxtaposition-or-indented-stack";
  }
  LOG(FATAL) << "Unknown partition policy " << int(p);
}

static void TokenFormatter(std::string* out, const PreFormatToken& token,
                           bool verbose) {
  if (verbose) {
    std::ostringstream oss;
    token.before.CompactNotation(oss);
    absl::StrAppend(out, oss.str());
  }
  absl::StrAppend(out, token.Text());
}

void UnwrappedLine::SetIndentationSpaces(int spaces) {
  CHECK_GE(spaces, 0);
  indentation_spaces_ = spaces;
}

void UnwrappedLine::DefaultOriginPrinter(std::ostream& stream,
                                         const verible::Symbol* symbol) {
  static constexpr int kContextLimit = 25;
  stream << '"' << AutoTruncate{StringSpanOfSymbol(*symbol), kContextLimit}
         << '"';
}

std::ostream* UnwrappedLine::AsCode(
    std::ostream* stream, bool verbose,
    const OriginPrinterFunction& origin_printer) const {
  *stream << Spacer(indentation_spaces_, kIndentationMarker) << '['
          << absl::StrJoin(tokens_, " ",
                           [=](std::string* out, const PreFormatToken& token) {
                             TokenFormatter(out, token, verbose);
                           })
          << "], policy: " << partition_policy_;
  if (origin_ != nullptr) {
    *stream << ", (origin: ";
    origin_printer(*stream, origin_);
    *stream << ")";
  }
  return stream;
}

std::ostream& operator<<(std::ostream& stream, const UnwrappedLine& line) {
  return *line.AsCode(&stream);
}

FormattedExcerpt::FormattedExcerpt(const UnwrappedLine& uwline)
    : indentation_spaces_(uwline.IndentationSpaces()) {
  tokens_.reserve(uwline.Size());
  // Convert working PreFormatTokens (computed from wrap optimization) into
  // decision-bound representation.
  const auto range = uwline.TokensRange();
  std::transform(range.begin(), range.end(), std::back_inserter(tokens_),
                 [](const PreFormatToken& t) { return FormattedToken(t); });
}

std::ostream& FormattedExcerpt::FormattedText(
    std::ostream& stream, bool indent,
    const std::function<bool(const TokenInfo&)>& include_token_p) const {
  if (tokens_.empty()) return stream;
  // Let caller print the preceding/trailing newline.
  if (indent) {
    if (tokens_.front().before.action != SpacingDecision::Preserve) {
      stream << Spacer(IndentationSpaces());
    }
  }
  // We do not want the indentation before the first token, if it was
  // already handled separately.
  const auto& front = tokens_.front();
  if (include_token_p(*front.token)) {
    VLOG(2) << "action: " << front.before.action;
    switch (front.before.action) {
      case SpacingDecision::Align:
        // When aligning tokens, the first token might be further indented.
        stream << Spacer(front.before.spaces) << front.token->text();
        break;
      default:
        stream << front.token->text();
    }
  }
  for (const auto& ftoken :
       verible::make_range(tokens_.begin() + 1, tokens_.end())) {
    if (include_token_p(*ftoken.token)) stream << ftoken;
  }
  return stream;
}

std::ostream& operator<<(std::ostream& stream,
                         const FormattedExcerpt& excerpt) {
  return excerpt.FormattedText(stream, true);
}

std::string FormattedExcerpt::Render() const {
  std::ostringstream stream;
  FormattedText(stream, true);
  return stream.str();
}

}  // namespace verible
