// 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::EscapeString;

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.LastLineOffset();
  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, bool include_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)) {
      VLOG(3) << "output: 1*\"\\n\" (empty space text)";
      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) {
    if (include_disabled_ranges) {  // for disabled intervals, print the
                                    // original spacing
      const absl::string_view disabled(
          text_base.substr(next_start, range.first - next_start));
      VLOG(3) << "output: \"" << EscapeString{disabled} << "\" (preserved)";
      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) << "output: " << newline_count << "*\"\\n\" (formatted)";
      stream << verible::Spacer(newline_count, '\n');
      partially_enabled = true;
      total_enabled_newlines += newline_count;
    }
    next_start = range.second;
  }
  if (include_disabled_ranges) {
    // If there is a disabled interval left over, print that.
    const absl::string_view final_disabled(
        text_base.substr(next_start, end - next_start));
    VLOG(3) << "output: \"" << EscapeString(final_disabled)
            << "\" (remaining disabled)";
    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) {
    VLOG(3) << "output: 1*\"\\n\"";
    stream << '\n';
  }
}

}  // namespace formatter
}  // namespace verilog
