#include "http2/adapter/oghttp2_adapter.h"

#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
#include "http2/adapter/http2_util.h"
#include "common/platform/api/quiche_bug_tracker.h"
#include "spdy/core/spdy_protocol.h"

namespace http2 {
namespace adapter {

namespace {

using spdy::SpdyFrameIR;
using spdy::SpdyGoAwayIR;
using spdy::SpdyPingIR;
using spdy::SpdyPriorityIR;
using spdy::SpdySettingsIR;
using spdy::SpdyWindowUpdateIR;

}  // namespace

/* static */
std::unique_ptr<OgHttp2Adapter> OgHttp2Adapter::Create(
    Http2VisitorInterface& visitor,
    Options options) {
  // Using `new` to access a non-public constructor.
  return absl::WrapUnique(new OgHttp2Adapter(visitor, std::move(options)));
}

OgHttp2Adapter::~OgHttp2Adapter() {}

bool OgHttp2Adapter::IsServerSession() const {
  return session_->IsServerSession();
}

int64_t OgHttp2Adapter::ProcessBytes(absl::string_view bytes) {
  return session_->ProcessBytes(bytes);
}

void OgHttp2Adapter::SubmitSettings(absl::Span<const Http2Setting> settings) {
  auto settings_ir = absl::make_unique<SpdySettingsIR>();
  for (const Http2Setting& setting : settings) {
    settings_ir->AddSetting(setting.id, setting.value);
  }
  session_->EnqueueFrame(std::move(settings_ir));
}

void OgHttp2Adapter::SubmitPriorityForStream(Http2StreamId stream_id,
                                             Http2StreamId parent_stream_id,
                                             int weight,
                                             bool exclusive) {
  session_->EnqueueFrame(absl::make_unique<SpdyPriorityIR>(
      stream_id, parent_stream_id, weight, exclusive));
}

void OgHttp2Adapter::SubmitPing(Http2PingId ping_id) {
  session_->EnqueueFrame(absl::make_unique<SpdyPingIR>(ping_id));
}

void OgHttp2Adapter::SubmitShutdownNotice() {
  session_->StartGracefulShutdown();
}

void OgHttp2Adapter::SubmitGoAway(Http2StreamId last_accepted_stream_id,
                                  Http2ErrorCode error_code,
                                  absl::string_view opaque_data) {
  session_->EnqueueFrame(absl::make_unique<SpdyGoAwayIR>(
      last_accepted_stream_id, TranslateErrorCode(error_code),
      std::string(opaque_data)));
}
void OgHttp2Adapter::SubmitWindowUpdate(Http2StreamId stream_id,
                                        int window_increment) {
  session_->EnqueueFrame(
      absl::make_unique<SpdyWindowUpdateIR>(stream_id, window_increment));
}

void OgHttp2Adapter::SubmitMetadata(Http2StreamId stream_id,
                                    std::unique_ptr<MetadataSource> source) {
  session_->SubmitMetadata(stream_id, std::move(source));
}

int OgHttp2Adapter::Send() { return session_->Send(); }

int OgHttp2Adapter::GetSendWindowSize() const {
  return session_->GetRemoteWindowSize();
}

int OgHttp2Adapter::GetStreamSendWindowSize(Http2StreamId stream_id) const {
  return session_->GetStreamSendWindowSize(stream_id);
}

int OgHttp2Adapter::GetStreamReceiveWindowLimit(Http2StreamId stream_id) const {
  return session_->GetStreamReceiveWindowLimit(stream_id);
}

int OgHttp2Adapter::GetStreamReceiveWindowSize(Http2StreamId stream_id) const {
  return session_->GetStreamReceiveWindowSize(stream_id);
}

int OgHttp2Adapter::GetReceiveWindowSize() const {
  return session_->GetReceiveWindowSize();
}

int OgHttp2Adapter::GetHpackEncoderDynamicTableSize() const {
  return session_->GetHpackEncoderDynamicTableSize();
}

int OgHttp2Adapter::GetHpackDecoderDynamicTableSize() const {
  return session_->GetHpackDecoderDynamicTableSize();
}

Http2StreamId OgHttp2Adapter::GetHighestReceivedStreamId() const {
  return session_->GetHighestReceivedStreamId();
}

void OgHttp2Adapter::MarkDataConsumedForStream(Http2StreamId stream_id,
                                               size_t num_bytes) {
  session_->Consume(stream_id, num_bytes);
}

void OgHttp2Adapter::SubmitRst(Http2StreamId stream_id,
                               Http2ErrorCode error_code) {
  session_->EnqueueFrame(absl::make_unique<spdy::SpdyRstStreamIR>(
      stream_id, TranslateErrorCode(error_code)));
}

int32_t OgHttp2Adapter::SubmitRequest(
    absl::Span<const Header> headers,
    std::unique_ptr<DataFrameSource> data_source, void* user_data) {
  return session_->SubmitRequest(headers, std::move(data_source), user_data);
}

int OgHttp2Adapter::SubmitResponse(
    Http2StreamId stream_id, absl::Span<const Header> headers,
    std::unique_ptr<DataFrameSource> data_source) {
  return session_->SubmitResponse(stream_id, headers, std::move(data_source));
}

int OgHttp2Adapter::SubmitTrailer(Http2StreamId stream_id,
                                  absl::Span<const Header> trailers) {
  return session_->SubmitTrailer(stream_id, trailers);
}

void OgHttp2Adapter::SetStreamUserData(Http2StreamId stream_id,
                                       void* user_data) {
  session_->SetStreamUserData(stream_id, user_data);
}

void* OgHttp2Adapter::GetStreamUserData(Http2StreamId stream_id) {
  return session_->GetStreamUserData(stream_id);
}

bool OgHttp2Adapter::ResumeStream(Http2StreamId stream_id) {
  return session_->ResumeStream(stream_id);
}

const Http2Session& OgHttp2Adapter::session() const {
  return *session_;
}

OgHttp2Adapter::OgHttp2Adapter(Http2VisitorInterface& visitor, Options options)
    : Http2Adapter(visitor),
      session_(absl::make_unique<OgHttp2Session>(visitor, std::move(options))) {
}

}  // namespace adapter
}  // namespace http2
