/** @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.
 */

#pragma once

#include "tscore/Allocator.h"
#include "tscore/ink_memory.h"
#include "tscore/ink_assert.h"
#include "iocore/net/quic/QUICApplication.h"
#include "proxy/http3/Http3Types.h"

class Http3Frame
{
public:
  constexpr static size_t MAX_FRAM_HEADER_OVERHEAD = 128; ///< Type (i) + Length (i)

  Http3Frame() {}
  Http3Frame(IOBufferReader &reader);
  Http3Frame(Http3FrameType type);
  virtual ~Http3Frame();

  bool                       is_valid() const;
  uint64_t                   total_length() const;
  uint64_t                   length() const;
  Http3FrameType             type() const;
  bool                       update();
  virtual Ptr<IOBufferBlock> to_io_buffer_block() const;
  virtual void               reset(IOBufferReader &reader);
  static int                 length(const uint8_t *buf, size_t buf_len, uint64_t &length);
  static Http3FrameType      type(const uint8_t *buf, size_t buf_len);

protected:
  IOBufferReader *_reader           = nullptr;
  bool            _finished_reading = false;
  uint64_t        _length           = 0;
  Http3FrameType  _type             = Http3FrameType::UNKNOWN;
  size_t          _payload_offset   = 0;
  bool            _is_valid         = true;

  virtual bool _parse();

private:
  bool _is_ready = false;
};

//
// DATA Frame
//

class Http3DataFrame : public Http3Frame
{
public:
  Http3DataFrame() : Http3Frame() {}
  Http3DataFrame(IOBufferReader &reader);
  Http3DataFrame(IOBufferReader &reader, size_t payload_len);

  Ptr<IOBufferBlock> to_io_buffer_block() const override;
  void               reset(IOBufferReader &reader) override;

  uint64_t payload_length() const;

  IOBufferReader *data() const;

private:
  // Head of IOBufferBlock chain to send
  Ptr<IOBufferBlock> _whole_frame;
  uint64_t           _payload_len = 0;

protected:
  bool _parse() override;
};

//
// HEADERS Frame
//

class Http3HeadersFrame : public Http3Frame
{
public:
  Http3HeadersFrame() : Http3Frame() {}
  Http3HeadersFrame(IOBufferReader &reader);
  // Shares the caller's buffer via a cloned reader instead of copying header_block_len bytes.
  // Safe as long as the source MIOBuffer outlives this frame, which holds for the qmux/quic
  // write path: the frame is created, serialized via to_io_buffer_block(), and destroyed, all
  // synchronously, well within the lifetime of the Http3HeaderFramer that owns the source buffer.
  Http3HeadersFrame(IOBufferReader &header_block_reader, size_t header_block_len);
  ~Http3HeadersFrame();

  Ptr<IOBufferBlock> to_io_buffer_block() const override;
  void               reset(IOBufferReader &reader) override;

  const uint8_t *header_block() const;
  uint64_t       header_block_length() const;

protected:
  bool _parse() override;

private:
  uint8_t        *_header_block        = nullptr;
  size_t          _header_block_len    = 0;
  IOBufferReader *_header_block_reader = nullptr;
};

//
// SETTINGS Frame
//

class Http3SettingsFrame : public Http3Frame
{
public:
  Http3SettingsFrame() : Http3Frame(Http3FrameType::SETTINGS) {}
  Http3SettingsFrame(IOBufferReader &reader, uint32_t max_settings = 0);

  static constexpr size_t                         MAX_PAYLOAD_SIZE = 60;
  static constexpr std::array<Http3SettingsId, 4> VALID_SETTINGS_IDS{
    Http3SettingsId::HEADER_TABLE_SIZE,
    Http3SettingsId::MAX_FIELD_SECTION_SIZE,
    Http3SettingsId::QPACK_BLOCKED_STREAMS,
    Http3SettingsId::NUM_PLACEHOLDERS,
  };

  Ptr<IOBufferBlock> to_io_buffer_block() const override;
  void               reset(IOBufferReader &reader) override;

  Http3ErrorUPtr get_error() const;

  bool     contains(Http3SettingsId id) const;
  uint64_t get(Http3SettingsId id) const;
  void     set(Http3SettingsId id, uint64_t value);

protected:
  bool _parse() override;

private:
  uint32_t                            _max_settings = 0;
  std::map<Http3SettingsId, uint64_t> _settings;
  Http3ErrorCode                      _error_code;
  const char                         *_error_reason = nullptr;
};

using Http3FrameDeleterFunc  = void (*)(Http3Frame *p);
using Http3FrameUPtr         = std::unique_ptr<Http3Frame, Http3FrameDeleterFunc>;
using Http3DataFrameUPtr     = std::unique_ptr<Http3DataFrame, Http3FrameDeleterFunc>;
using Http3HeadersFrameUPtr  = std::unique_ptr<Http3HeadersFrame, Http3FrameDeleterFunc>;
using Http3SettingsFrameUPtr = std::unique_ptr<Http3SettingsFrame, Http3FrameDeleterFunc>;

using Http3FrameDeleterFunc = void (*)(Http3Frame *p);
using Http3FrameUPtr        = std::unique_ptr<Http3Frame, Http3FrameDeleterFunc>;
using Http3DataFrameUPtr    = std::unique_ptr<Http3DataFrame, Http3FrameDeleterFunc>;
using Http3HeadersFrameUPtr = std::unique_ptr<Http3HeadersFrame, Http3FrameDeleterFunc>;

extern ClassAllocator<Http3Frame, false>         http3FrameAllocator;
extern ClassAllocator<Http3DataFrame, false>     http3DataFrameAllocator;
extern ClassAllocator<Http3HeadersFrame, false>  http3HeadersFrameAllocator;
extern ClassAllocator<Http3SettingsFrame, false> http3SettingsFrameAllocator;

class Http3FrameDeleter
{
public:
  static void
  delete_null_frame(Http3Frame *frame)
  {
    ink_assert(frame == nullptr);
  }

  static void
  delete_frame(Http3Frame *frame)
  {
    frame->~Http3Frame();
    http3FrameAllocator.free(static_cast<Http3Frame *>(frame));
  }

  static void
  delete_data_frame(Http3Frame *frame)
  {
    frame->~Http3Frame();
    http3DataFrameAllocator.free(static_cast<Http3DataFrame *>(frame));
  }

  static void
  delete_headers_frame(Http3Frame *frame)
  {
    frame->~Http3Frame();
    http3HeadersFrameAllocator.free(static_cast<Http3HeadersFrame *>(frame));
  }

  static void
  delete_settings_frame(Http3Frame *frame)
  {
    frame->~Http3Frame();
    http3SettingsFrameAllocator.free(static_cast<Http3SettingsFrame *>(frame));
  }
};

//
// Http3FrameFactory
//
class Http3FrameFactory
{
public:
  /*
   * This is for an empty Http3FrameUPtr.
   * Empty frames are used for variable initialization and return value of frame creation failure
   */
  static Http3FrameUPtr create_null_frame();

  /*
   * This is used for creating a Http3Frame object based on received data.
   */
  static Http3FrameUPtr create(IOBufferReader &reader);

  /*
   * This works almost the same as create() but it reuses created objects for performance.
   * If you create a frame object which has the same frame type that you created before, the object will be reset by new data.
   */
  std::shared_ptr<Http3Frame> fast_create(IOBufferReader &reader);

  /*
   * Creates a HEADERS frame.
   */
  static Http3HeadersFrameUPtr create_headers_frame(IOBufferReader *header_block_reader, size_t header_block_len);

  /*
   * Creates a DATA frame.
   */
  static Http3DataFrameUPtr create_data_frame(IOBufferReader *reader, size_t data_len);

private:
  std::shared_ptr<Http3Frame> _unknown_frame        = nullptr;
  std::shared_ptr<Http3Frame> _reusable_frames[256] = {nullptr};
};
