#include "spdy/core/metadata_extension.h"

#include <list>
#include <string>

#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
#include "http2/decoder/decode_buffer.h"
#include "http2/hpack/decoder/hpack_decoder.h"
#include "common/platform/api/quiche_bug_tracker.h"
#include "common/platform/api/quiche_logging.h"
#include "spdy/core/hpack/hpack_encoder.h"
#include "spdy/core/http2_header_block_hpack_listener.h"

namespace spdy {

// Non-standard constants related to METADATA frames.
const SpdySettingsId MetadataVisitor::kMetadataExtensionId = 0x4d44;
const uint8_t MetadataVisitor::kMetadataFrameType = 0x4d;
const uint8_t MetadataVisitor::kEndMetadataFlag = 0x4;

namespace {

const size_t kMaxMetadataBlockSize = 1 << 20;  // 1 MB

// This class uses an HpackEncoder to serialize a METADATA block as a series of
// METADATA frames.
class MetadataFrameSequence : public MetadataSerializer::FrameSequence {
 public:
  MetadataFrameSequence(SpdyStreamId stream_id, spdy::SpdyHeaderBlock payload)
      : stream_id_(stream_id), payload_(std::move(payload)) {
    // Metadata should not use HPACK compression.
    encoder_.DisableCompression();
    HpackEncoder::Representations r;
    for (const auto& kv_pair : payload_) {
      r.push_back(kv_pair);
    }
    progressive_encoder_ = encoder_.EncodeRepresentations(r);
  }

  // Copies are not allowed.
  MetadataFrameSequence(const MetadataFrameSequence& other) = delete;
  MetadataFrameSequence& operator=(const MetadataFrameSequence& other) = delete;

  std::unique_ptr<spdy::SpdyFrameIR> Next() override;

 private:
  SpdyStreamId stream_id_;
  SpdyHeaderBlock payload_;
  HpackEncoder encoder_;
  std::unique_ptr<HpackEncoder::ProgressiveEncoder> progressive_encoder_;
};

std::unique_ptr<spdy::SpdyFrameIR> MetadataFrameSequence::Next() {
  if (!progressive_encoder_->HasNext()) {
    return nullptr;
  }
  // METADATA frames obey the HTTP/2 maximum frame size.
  std::string payload =
      progressive_encoder_->Next(spdy::kHttp2DefaultFramePayloadLimit);
  const bool end_metadata = (!progressive_encoder_->HasNext());
  const uint8_t flags = end_metadata ? MetadataVisitor::kEndMetadataFlag : 0;
  return absl::make_unique<spdy::SpdyUnknownIR>(
      stream_id_, MetadataVisitor::kMetadataFrameType, flags,
      std::move(payload));
}

}  // anonymous namespace

struct MetadataVisitor::MetadataPayloadState {
  MetadataPayloadState(size_t remaining, bool end)
      : bytes_remaining(remaining), end_metadata(end) {}
  std::list<std::string> buffer;
  size_t bytes_remaining;
  bool end_metadata;
};

MetadataVisitor::MetadataVisitor(OnCompletePayload on_payload,
                                 OnMetadataSupport on_support)
    : on_payload_(std::move(on_payload)),
      on_support_(std::move(on_support)),
      peer_supports_metadata_(MetadataSupportState::UNSPECIFIED) {}

MetadataVisitor::~MetadataVisitor() {}

void MetadataVisitor::OnSetting(SpdySettingsId id, uint32_t value) {
  QUICHE_VLOG(1) << "MetadataVisitor::OnSetting(" << id << ", " << value << ")";
  if (id == kMetadataExtensionId) {
    if (value == 0) {
      const MetadataSupportState previous_state = peer_supports_metadata_;
      peer_supports_metadata_ = MetadataSupportState::NOT_SUPPORTED;
      if (previous_state == MetadataSupportState::UNSPECIFIED ||
          previous_state == MetadataSupportState::SUPPORTED) {
        on_support_(false);
      }
    } else if (value == 1) {
      const MetadataSupportState previous_state = peer_supports_metadata_;
      peer_supports_metadata_ = MetadataSupportState::SUPPORTED;
      if (previous_state == MetadataSupportState::UNSPECIFIED ||
          previous_state == MetadataSupportState::NOT_SUPPORTED) {
        on_support_(true);
      }
    } else {
      LOG_EVERY_N_SEC(WARNING, 1)
          << "Unrecognized value for setting " << id << ": " << value;
    }
  }
}

bool MetadataVisitor::OnFrameHeader(SpdyStreamId stream_id, size_t length,
                                    uint8_t type, uint8_t flags) {
  QUICHE_VLOG(1) << "OnFrameHeader(stream_id=" << stream_id
                 << ", length=" << length << ", type=" << static_cast<int>(type)
                 << ", flags=" << static_cast<int>(flags);
  // TODO(birenroy): Consider disabling METADATA handling until our setting
  // advertising METADATA support has been acked.
  if (type != kMetadataFrameType) {
    return false;
  }
  auto it = metadata_map_.find(stream_id);
  if (it == metadata_map_.end()) {
    auto state = absl::make_unique<MetadataPayloadState>(
        length, flags & kEndMetadataFlag);
    auto result = metadata_map_.insert(std::make_pair(stream_id,
                                                      std::move(state)));
    QUICHE_BUG_IF(bug_if_2781_1, !result.second) << "Map insertion failed.";
    it = result.first;
  } else {
    QUICHE_BUG_IF(bug_22051_1, it->second->end_metadata)
        << "Inconsistent metadata payload state!";
    QUICHE_BUG_IF(bug_if_2781_2, it->second->bytes_remaining > 0)
        << "Incomplete metadata block!";
  }

  if (it->second == nullptr) {
    QUICHE_BUG(bug_2781_3) << "Null metadata payload state!";
    return false;
  }
  current_stream_ = stream_id;
  it->second->bytes_remaining = length;
  it->second->end_metadata = (flags & kEndMetadataFlag);
  return true;
}

void MetadataVisitor::OnFramePayload(const char* data, size_t len) {
  QUICHE_VLOG(1) << "OnFramePayload(stream_id=" << current_stream_
                 << ", len=" << len << ")";
  auto it = metadata_map_.find(current_stream_);
  if (it == metadata_map_.end() || it->second == nullptr) {
    QUICHE_BUG(bug_2781_4) << "Invalid order of operations on MetadataVisitor.";
  } else {
    MetadataPayloadState* state = it->second.get();  // For readability.
    state->buffer.push_back(std::string(data, len));
    if (len < state->bytes_remaining) {
      state->bytes_remaining -= len;
    } else {
      QUICHE_BUG_IF(bug_22051_2, len > state->bytes_remaining)
          << "Metadata payload overflow! len: " << len
          << " bytes_remaining: " << state->bytes_remaining;
      state->bytes_remaining = 0;
      if (state->end_metadata) {
        // The whole process of decoding the HPACK-encoded metadata block,
        // below, is more cumbersome than it ought to be.
        spdy::Http2HeaderBlockHpackListener listener;
        http2::HpackDecoder decoder(&listener, kMaxMetadataBlockSize);

        // If any operations fail, the decode process should be aborted.
        bool success = decoder.StartDecodingBlock();
        for (const std::string& slice : state->buffer) {
          if (!success) {
            break;
          }
          http2::DecodeBuffer buffer(slice.data(), slice.size());
          success = success && decoder.DecodeFragment(&buffer);
        }
        success =
            success && decoder.EndDecodingBlock() && !listener.hpack_error();
        if (success) {
          on_payload_(current_stream_, listener.release_header_block());
        }
        // TODO(birenroy): add varz counting metadata decode successes/failures.
        metadata_map_.erase(it);
      }
    }
  }
}

std::unique_ptr<MetadataSerializer::FrameSequence>
MetadataSerializer::FrameSequenceForPayload(SpdyStreamId stream_id,
                                            MetadataPayload payload) {
  return absl::make_unique<MetadataFrameSequence>(stream_id,
                                                  std::move(payload));
}

}  // namespace spdy
