#include "http2/adapter/test_utils.h"

#include <ostream>

#include "absl/strings/str_format.h"
#include "http2/adapter/http2_visitor_interface.h"
#include "common/quiche_data_reader.h"
#include "spdy/core/hpack/hpack_encoder.h"

namespace http2 {
namespace adapter {
namespace test {
namespace {

using ConnectionError = Http2VisitorInterface::ConnectionError;

}  // anonymous namespace

TestDataFrameSource::TestDataFrameSource(Http2VisitorInterface& visitor,
                                         bool has_fin)
    : visitor_(visitor), has_fin_(has_fin) {}

void TestDataFrameSource::AppendPayload(absl::string_view payload) {
  QUICHE_CHECK(!end_data_);
  if (!payload.empty()) {
    payload_fragments_.push_back(std::string(payload));
    current_fragment_ = payload_fragments_.front();
  }
}

void TestDataFrameSource::EndData() { end_data_ = true; }

std::pair<int64_t, bool> TestDataFrameSource::SelectPayloadLength(
    size_t max_length) {
  if (return_error_) {
    return {DataFrameSource::kError, false};
  }
  // The stream is done if there's no more data, or if |max_length| is at least
  // as large as the remaining data.
  const bool end_data = end_data_ && (current_fragment_.empty() ||
                                      (payload_fragments_.size() == 1 &&
                                       max_length >= current_fragment_.size()));
  const int64_t length = std::min(max_length, current_fragment_.size());
  return {length, end_data};
}

bool TestDataFrameSource::Send(absl::string_view frame_header,
                               size_t payload_length) {
  QUICHE_LOG_IF(DFATAL, payload_length > current_fragment_.size())
      << "payload_length: " << payload_length
      << " current_fragment_size: " << current_fragment_.size();
  const std::string concatenated =
      absl::StrCat(frame_header, current_fragment_.substr(0, payload_length));
  const int64_t result = visitor_.OnReadyToSend(concatenated);
  if (result < 0) {
    // Write encountered error.
    visitor_.OnConnectionError(ConnectionError::kSendError);
    current_fragment_ = {};
    payload_fragments_.clear();
    return false;
  } else if (result == 0) {
    // Write blocked.
    return false;
  } else if (static_cast<const size_t>(result) < concatenated.size()) {
    // Probably need to handle this better within this test class.
    QUICHE_LOG(DFATAL)
        << "DATA frame not fully flushed. Connection will be corrupt!";
    visitor_.OnConnectionError(ConnectionError::kSendError);
    current_fragment_ = {};
    payload_fragments_.clear();
    return false;
  }
  if (payload_length > 0) {
    current_fragment_.remove_prefix(payload_length);
  }
  if (current_fragment_.empty() && !payload_fragments_.empty()) {
    payload_fragments_.erase(payload_fragments_.begin());
    if (!payload_fragments_.empty()) {
      current_fragment_ = payload_fragments_.front();
    }
  }
  return true;
}

std::string EncodeHeaders(const spdy::SpdyHeaderBlock& entries) {
  spdy::HpackEncoder encoder;
  encoder.DisableCompression();
  return encoder.EncodeHeaderBlock(entries);
}

TestMetadataSource::TestMetadataSource(const spdy::SpdyHeaderBlock& entries)
    : encoded_entries_(EncodeHeaders(entries)) {
  remaining_ = encoded_entries_;
}

std::pair<int64_t, bool> TestMetadataSource::Pack(uint8_t* dest,
                                                  size_t dest_len) {
  const size_t copied = std::min(dest_len, remaining_.size());
  std::memcpy(dest, remaining_.data(), copied);
  remaining_.remove_prefix(copied);
  return std::make_pair(copied, remaining_.empty());
}

namespace {

using TypeAndOptionalLength =
    std::pair<spdy::SpdyFrameType, absl::optional<size_t>>;

std::ostream& operator<<(
    std::ostream& os,
    const std::vector<TypeAndOptionalLength>& types_and_lengths) {
  for (const auto& type_and_length : types_and_lengths) {
    os << "(" << spdy::FrameTypeToString(type_and_length.first) << ", "
       << (type_and_length.second ? absl::StrCat(type_and_length.second.value())
                                  : "<unspecified>")
       << ") ";
  }
  return os;
}

std::string FrameTypeToString(uint8_t frame_type) {
  if (spdy::IsDefinedFrameType(frame_type)) {
    return spdy::FrameTypeToString(spdy::ParseFrameType(frame_type));
  } else {
    return absl::StrFormat("0x%x", static_cast<int>(frame_type));
  }
}

// Custom gMock matcher, used to implement EqualsFrames().
class SpdyControlFrameMatcher
    : public testing::MatcherInterface<absl::string_view> {
 public:
  explicit SpdyControlFrameMatcher(
      std::vector<TypeAndOptionalLength> types_and_lengths)
      : expected_types_and_lengths_(std::move(types_and_lengths)) {}

  bool MatchAndExplain(absl::string_view s,
                       testing::MatchResultListener* listener) const override {
    quiche::QuicheDataReader reader(s.data(), s.size());

    for (TypeAndOptionalLength expected : expected_types_and_lengths_) {
      if (!MatchAndExplainOneFrame(expected.first, expected.second, &reader,
                                   listener)) {
        return false;
      }
    }
    if (!reader.IsDoneReading()) {
      *listener << "; " << reader.BytesRemaining() << " bytes left to read!";
      return false;
    }
    return true;
  }

  bool MatchAndExplainOneFrame(spdy::SpdyFrameType expected_type,
                               absl::optional<size_t> expected_length,
                               quiche::QuicheDataReader* reader,
                               testing::MatchResultListener* listener) const {
    uint32_t payload_length;
    if (!reader->ReadUInt24(&payload_length)) {
      *listener << "; unable to read length field for expected_type "
                << FrameTypeToString(expected_type) << ". data too short!";
      return false;
    }

    if (expected_length && payload_length != expected_length.value()) {
      *listener << "; actual length: " << payload_length
                << " but expected length: " << expected_length.value();
      return false;
    }

    uint8_t raw_type;
    if (!reader->ReadUInt8(&raw_type)) {
      *listener << "; unable to read type field for expected_type "
                << FrameTypeToString(expected_type) << ". data too short!";
      return false;
    }

    if (raw_type != static_cast<uint8_t>(expected_type)) {
      *listener << "; actual type: " << FrameTypeToString(raw_type)
                << " but expected type: " << FrameTypeToString(expected_type);
      return false;
    }

    // Seek past flags (1B), stream ID (4B), and payload. Reach the next frame.
    reader->Seek(5 + payload_length);
    return true;
  }

  void DescribeTo(std::ostream* os) const override {
    *os << "Data contains frames of types in sequence "
        << expected_types_and_lengths_;
  }

  void DescribeNegationTo(std::ostream* os) const override {
    *os << "Data does not contain frames of types in sequence "
        << expected_types_and_lengths_;
  }

 private:
  const std::vector<TypeAndOptionalLength> expected_types_and_lengths_;
};

}  // namespace

testing::Matcher<absl::string_view> EqualsFrames(
    std::vector<std::pair<spdy::SpdyFrameType, absl::optional<size_t>>>
        types_and_lengths) {
  return MakeMatcher(new SpdyControlFrameMatcher(std::move(types_and_lengths)));
}

testing::Matcher<absl::string_view> EqualsFrames(
    std::vector<spdy::SpdyFrameType> types) {
  std::vector<std::pair<spdy::SpdyFrameType, absl::optional<size_t>>>
      types_and_lengths;
  types_and_lengths.reserve(types.size());
  for (spdy::SpdyFrameType type : types) {
    types_and_lengths.push_back({type, absl::nullopt});
  }
  return MakeMatcher(new SpdyControlFrameMatcher(std::move(types_and_lengths)));
}

}  // namespace test
}  // namespace adapter
}  // namespace http2
