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

#include <iostream>
#include <vector>

#include "absl/strings/match.h"
#include "absl/strings/str_split.h"
#include "absl/strings/strip.h"
#include "common/strings/comment_utils.h"
#include "common/strings/display_utils.h"
#include "common/strings/line_column_map.h"
#include "common/util/logging.h"
#include "common/util/range.h"
#include "common/util/spacer.h"
#include "verilog/parser/verilog_parser.h"
#include "verilog/parser/verilog_token_classifications.h"
#include "verilog/parser/verilog_token_enum.h"

namespace verilog {
namespace formatter {

using verible::ByteOffsetSet;
using verible::VisualizeWhitespace;

ByteOffsetSet DisableFormattingRanges(absl::string_view text,
                                      const verible::TokenSequence& tokens) {
  static constexpr absl::string_view kTrigger = "verilog_format:";
  static const auto kDelimiters = absl::ByAnyChar(" \t");
  static constexpr int kNullOffset = -1;
  const verible::TokenInfo::Context context(
      text,
      [](std::ostream& stream, int e) { stream << verilog_symbol_name(e); });

  // By default, no text ranges are formatter-disabled.
  int begin_disable_offset = kNullOffset;
  ByteOffsetSet disable_set;
  for (const auto& token : tokens) {
    VLOG(2) << verible::TokenWithContext{token, context};
    const auto vtoken_enum = verilog_tokentype(token.token_enum());
    if (IsComment(vtoken_enum)) {
      // Focus on the space-delimited tokens in the comment text.
      auto commands = verible::StripCommentAndSpacePadding(token.text());
      if (absl::ConsumePrefix(&commands, kTrigger)) {
        const std::vector<absl::string_view> comment_tokens(
            absl::StrSplit(commands, kDelimiters, absl::SkipEmpty()));
        if (!comment_tokens.empty()) {
          // "off" marks the start of a disabling range, at end of comment.
          // "on" marks the end of disabling range, up to the end of comment.
          if (comment_tokens.front() == "off") {
            if (begin_disable_offset == kNullOffset) {
              begin_disable_offset = token.right(text);
              if (vtoken_enum == TK_EOL_COMMENT) {
                ++begin_disable_offset;  // to cover the trailing '\n'
              }
            }  // else ignore
          } else if (comment_tokens.front() == "on") {
            if (begin_disable_offset != kNullOffset) {
              const int end_disable_offset = token.right(text);
              if (begin_disable_offset != end_disable_offset) {
                disable_set.Add({begin_disable_offset, end_disable_offset});
              }
              begin_disable_offset = kNullOffset;
            }  // else ignore
          }
        }
      }
    }
  }
  // If the disabling interval remains open, close it (to end-of-buffer).
  if (begin_disable_offset != kNullOffset) {
    disable_set.Add({begin_disable_offset, static_cast<int>(text.length())});
  }
  return disable_set;
}

ByteOffsetSet EnabledLinesToDisabledByteRanges(
    const verible::LineNumberSet& line_numbers,
    const verible::LineColumnMap& line_column_map) {
  // Interpret empty line numbers as enabling all lines for formatting.
  if (line_numbers.empty()) return ByteOffsetSet();
  // Translate lines to byte offsets (strictly monotonic).
  const int max_line = line_column_map.GetBeginningOfLineOffsets().size() + 1;
  ByteOffsetSet byte_offsets(
      line_numbers.MonotonicTransform<int>([&](int line_number) {
        // line_numbers are 1-based, while OffsetAtLine is 0-based
        const int n = std::max(std::min(line_number, max_line), 1);
        return line_column_map.OffsetAtLine(n - 1);
      }));
  // Invert set to get disabled ranges.
  const int end_byte = line_column_map.EndOffset();
  byte_offsets.Complement({0, end_byte});
  return byte_offsets;
}

static size_t NewlineCount(absl::string_view s) {
  return std::count(s.begin(), s.end(), '\n');
}

void FormatWhitespaceWithDisabledByteRanges(
    absl::string_view text_base, absl::string_view space_text,
    const ByteOffsetSet& disabled_ranges, std::ostream& stream) {
  VLOG(3) << __FUNCTION__;
  CHECK(verible::IsSubRange(space_text, text_base));
  const int start = std::distance(text_base.begin(), space_text.begin());
  const int end = start + space_text.length();
  ByteOffsetSet enabled_ranges{{start, end}};  // initial interval set mask
  enabled_ranges.Difference(disabled_ranges);
  VLOG(3) << "space range: [" << start << ", " << end << ')';
  VLOG(3) << "disabled ranges: " << disabled_ranges;
  VLOG(3) << "enabled ranges: " << enabled_ranges;

  // Special case if space_text is empty.
  if (space_text.empty() && start != 0) {
    if (!disabled_ranges.Contains(start)) {
      stream << '\n';
      return;
    }
  }

  // Traverse alternating disabled and enabled ranges.
  bool partially_enabled = false;
  size_t total_enabled_newlines = 0;
  int next_start = start;  // keep track of last consumed position
  for (const auto& range : enabled_ranges) {
    {  // for disabled intervals, print the original spacing
      const absl::string_view disabled(
          text_base.substr(next_start, range.first - next_start));
      VLOG(3) << "preserved: \"" << VisualizeWhitespace{disabled} << '"';
      stream << disabled;
      total_enabled_newlines += NewlineCount(disabled);
    }
    {  // for enabled intervals, preserve only newlines
      const absl::string_view enabled(
          text_base.substr(range.first, range.second - range.first));
      const size_t newline_count = NewlineCount(enabled);
      VLOG(3) << "formatted: " << newline_count << "*\\n";
      stream << verible::Spacer(newline_count, '\n');
      partially_enabled = true;
      total_enabled_newlines += newline_count;
    }
    next_start = range.second;
  }
  // If there is a disabled interval left over, print that.
  const absl::string_view final_disabled(
      text_base.substr(next_start, end - next_start));
  stream << final_disabled;
  total_enabled_newlines += NewlineCount(final_disabled);

  // Print at least one newline if some subrange was format-enabled.
  if (partially_enabled && total_enabled_newlines == 0 && start != 0) {
    stream << '\n';
  }
}

}  // namespace formatter
}  // namespace verilog
