/** @file

  A brief file description

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you 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 "proxy/http3/Http3HeaderVIOAdaptor.h"
#include "proxy/http3/Http3Transaction.h"
#include "proxy/hdrs/HeaderValidator.h"

#include "iocore/eventsystem/VIO.h"
#include "proxy/hdrs/HTTP.h"

namespace
{
DbgCtl dbg_ctl_http3{"http3"};
DbgCtl dbg_ctl_v_http3{"v_http3"};

} // end anonymous namespace

Http3HeaderVIOAdaptor::Http3HeaderVIOAdaptor(VIO *sink, HTTPType http_type, QPACK *qpack, uint64_t stream_id, HQTransaction *txn)
  : _sink_vio(sink), _qpack(qpack), _stream_id(stream_id), _txn(txn)
{
  SET_HANDLER(&Http3HeaderVIOAdaptor::event_handler);

  this->_header.create(http_type);
}

Http3HeaderVIOAdaptor::~Http3HeaderVIOAdaptor()
{
  this->_header.destroy();
}

std::vector<Http3FrameType> const &
Http3HeaderVIOAdaptor::interests()
{
  static std::vector<Http3FrameType> const types = {Http3FrameType::HEADERS};
  return types;
}

Http3ErrorUPtr
Http3HeaderVIOAdaptor::handle_frame(std::shared_ptr<const Http3Frame> frame, Http3StreamType /* s_type */)
{
  ink_assert(frame->type() == Http3FrameType::HEADERS);
  const Http3HeadersFrame *hframe = dynamic_cast<const Http3HeadersFrame *>(frame.get());

  int res = this->_qpack->decode(this->_stream_id, hframe->header_block(), hframe->header_block_length(), _header, this);

  if (res == 0) {
    // When decoding is not blocked, continuation should be called directly?
  } else if (res == 1) {
    // Decoding is blocked.
    Dbg(dbg_ctl_http3, "Decoding is blocked. DecodeRequest is scheduled");
  } else if (res < 0) {
    Dbg(dbg_ctl_http3, "Error on decoding header (%d)", res);
  } else {
    ink_abort("should not be here");
  }

  return Http3ErrorUPtr(nullptr);
}

bool
Http3HeaderVIOAdaptor::is_complete()
{
  return this->_is_complete;
}

int
Http3HeaderVIOAdaptor::event_handler(int event, Event * /* data ATS_UNUSED */)
{
  switch (event) {
  case QPACK_EVENT_DECODE_COMPLETE:
    Dbg(dbg_ctl_v_http3, "%s (%d)", "QPACK_EVENT_DECODE_COMPLETE", event);
    if (this->_on_qpack_decode_complete()) {
      // If READ_READY event is scheduled, should it be canceled?
    }
    break;
  case QPACK_EVENT_DECODE_FAILED:
    Dbg(dbg_ctl_v_http3, "%s (%d)", "QPACK_EVENT_DECODE_FAILED", event);
    // FIXME: handle error
    break;
  }

  return EVENT_DONE;
}

int
Http3HeaderVIOAdaptor::_on_qpack_decode_complete()
{
  // Currently trailer support for h3 is not implemented.
  constexpr static bool NON_TRAILER = false;
  if (!HeaderValidator::is_h2_h3_header_valid(this->_header, http_hdr_type_get(this->_header.m_http) == HTTPType::RESPONSE,
                                              NON_TRAILER)) {
    Dbg(dbg_ctl_http3, "Header is invalid");
    if (this->_txn != nullptr) {
      this->_txn->log_non_http_sm_access(&this->_header, "http/3");
    }
    return -1;
  }
  int res = this->_hvc.convert(this->_header, 3, 1);
  if (res != 0) {
    Dbg(dbg_ctl_http3, "ParseResult::ERROR");
    if (this->_txn != nullptr) {
      this->_txn->log_non_http_sm_access(&this->_header, "http/3");
    }
    return -1;
  }

  // FIXME: response header might be delayed from first response body because of callback from QPACK
  // Workaround fix for mixed response header and body
  if (http_hdr_type_get(this->_header.m_http) == HTTPType::RESPONSE) {
    return 0;
  }

  SCOPED_MUTEX_LOCK(lock, this->_sink_vio->mutex, this_ethread());
  MIOBuffer *writer = this->_sink_vio->get_writer();

  // TODO: Http2Stream::send_request has same logic. It originally comes from HttpSM::write_header_into_buffer.
  // a). Make HttpSM::write_header_into_buffer static
  //   or
  // b). Add interface to HTTPHdr to dump data
  //   or
  // c). Add interface to HttpSM to handle HTTPHdr directly
  int            bufindex;
  int            dumpoffset    = 0;
  int64_t        header_length = 0;
  int            done, tmp;
  IOBufferBlock *block;
  do {
    bufindex = 0;
    tmp      = dumpoffset;
    block    = writer->get_current_block();
    if (!block) {
      writer->add_block();
      block = writer->get_current_block();
    }
    done           = this->_header.print(block->end(), block->write_avail(), &bufindex, &tmp);
    dumpoffset    += bufindex;
    header_length += bufindex;
    writer->fill(bufindex);
    if (!done) {
      writer->add_block();
    }
  } while (!done);

  this->_sink_vio->ndone += header_length;
  this->_is_complete      = true;
  if (auto *transaction = dynamic_cast<Http3Transaction *>(this->_txn); transaction != nullptr) {
    transaction->on_header_decode_complete();
  }
  return 1;
}
