// 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 <algorithm>
#include <cstddef>
#include <iostream>
#include <iterator>
#include <vector>

#include "absl/strings/str_split.h"
#include "absl/strings/string_view.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/strings/position.h"
#include "common/text/token_info.h"
#include "common/text/token_stream_view.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).
  int text_length = static_cast<int>(text.length());
  if (begin_disable_offset != kNullOffset &&
      begin_disable_offset <= text_length) {
    disable_set.Add({begin_disable_offset, 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
