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

/**
 * @file AsyncHttpFetch.cc
 */

#include <memory>
#include <arpa/inet.h>
#include "tscpp/api/AsyncHttpFetch.h"
#include "ts/ts.h"
#include "logging_internal.h"
#include "utils_internal.h"

#include <cstdio>
#include <cstring>
#include <utility>

using namespace atscppapi;

using std::string;

/**
 * @private
 */
struct atscppapi::AsyncHttpFetchState : noncopyable {
  std::shared_ptr<Request>                     request_;
  Response                                     response_;
  string                                       request_body_;
  AsyncHttpFetch::Result                       result_;
  const void                                  *body_;
  size_t                                       body_size_;
  TSMBuffer                                    hdr_buf_;
  TSMLoc                                       hdr_loc_;
  std::shared_ptr<AsyncDispatchControllerBase> dispatch_controller_;
  AsyncHttpFetch::StreamingFlag                streaming_flag_;
  TSFetchSM                                    fetch_sm_;
  static const size_t                          BODY_BUFFER_SIZE = 32 * 1024;
  char                                         body_buffer_[BODY_BUFFER_SIZE];

  AsyncHttpFetchState(const string &url_str, HttpMethod http_method, string request_body,
                      AsyncHttpFetch::StreamingFlag streaming_flag)
    : request_body_(std::move(request_body)),
      result_(AsyncHttpFetch::RESULT_FAILURE),
      body_(nullptr),
      body_size_(0),
      hdr_buf_(nullptr),
      hdr_loc_(nullptr),
      streaming_flag_(streaming_flag),
      fetch_sm_(nullptr)
  {
    request_.reset(new Request(url_str, http_method,
                               (streaming_flag_ == AsyncHttpFetch::STREAMING_DISABLED) ? HTTP_VERSION_1_0 : HTTP_VERSION_1_1));
    if (streaming_flag_ == AsyncHttpFetch::STREAMING_ENABLED) {
      body_ = body_buffer_;
    }
  }

  ~AsyncHttpFetchState()
  {
    if (hdr_loc_) {
      TSMLoc null_parent_loc = nullptr;
      TSHandleMLocRelease(hdr_buf_, null_parent_loc, hdr_loc_);
    }
    if (hdr_buf_) {
      TSMBufferDestroy(hdr_buf_);
    }
    if (fetch_sm_) {
      TSFetchDestroy(fetch_sm_);
    }
  }
};

namespace
{
const unsigned int LOCAL_IP_ADDRESS = 0x0100007f;
const int          LOCAL_PORT       = 8080;

static int
handleFetchEvents(TSCont cont, TSEvent event, void *edata)
{
  LOG_DEBUG("Received fetch event = %d, edata = %p", event, edata);
  AsyncHttpFetch      *fetch_provider = static_cast<AsyncHttpFetch *>(TSContDataGet(cont));
  AsyncHttpFetchState *state          = utils::internal::getAsyncHttpFetchState(*fetch_provider);

  if (state->streaming_flag_ == AsyncHttpFetch::STREAMING_DISABLED) {
    if (event == static_cast<int>(AsyncHttpFetch::RESULT_SUCCESS)) {
      TSHttpTxn   txn = static_cast<TSHttpTxn>(edata);
      int         data_len;
      const char *data_start = TSFetchRespGet(txn, &data_len);
      if (data_start && (data_len > 0)) {
        const char  *data_end = data_start + data_len;
        TSHttpParser parser   = TSHttpParserCreate();
        state->hdr_buf_       = TSMBufferCreate();
        state->hdr_loc_       = TSHttpHdrCreate(state->hdr_buf_);
        TSHttpHdrTypeSet(state->hdr_buf_, state->hdr_loc_, TS_HTTP_TYPE_RESPONSE);
        if (TSHttpHdrParseResp(parser, state->hdr_buf_, state->hdr_loc_, &data_start, data_end) == TS_PARSE_DONE) {
          TSHttpStatus status = TSHttpHdrStatusGet(state->hdr_buf_, state->hdr_loc_);
          state->body_        = data_start; // data_start will now be pointing to body
          state->body_size_   = data_end - data_start;
          utils::internal::initResponse(state->response_, state->hdr_buf_, state->hdr_loc_);
          LOG_DEBUG("Fetch result had a status code of %d with a body length of %ld", status, state->body_size_);
        } else {
          LOG_ERROR("Unable to parse response; Request URL [%s]; transaction %p", state->request_->getUrl().getUrlString().c_str(),
                    txn);
          event = static_cast<TSEvent>(AsyncHttpFetch::RESULT_FAILURE);
        }
        TSHttpParserDestroy(parser);
      } else {
        LOG_ERROR("Successful fetch did not result in any content. Assuming failure");
        event = static_cast<TSEvent>(AsyncHttpFetch::RESULT_FAILURE);
      }
      state->result_ = static_cast<AsyncHttpFetch::Result>(event);
    }
  } else {
    LOG_DEBUG("Handling streaming event %d", event);
    if (event == static_cast<TSEvent>(TS_FETCH_EVENT_EXT_HEAD_DONE)) {
      utils::internal::initResponse(state->response_, TSFetchRespHdrMBufGet(state->fetch_sm_),
                                    TSFetchRespHdrMLocGet(state->fetch_sm_));
      LOG_DEBUG("Response header initialized");
      state->result_ = AsyncHttpFetch::RESULT_HEADER_COMPLETE;
    } else {
      state->body_size_ = TSFetchReadData(state->fetch_sm_, state->body_buffer_, sizeof(state->body_buffer_));
      LOG_DEBUG("Read %zu bytes", state->body_size_);
      state->result_ = (event == static_cast<TSEvent>(TS_FETCH_EVENT_EXT_BODY_READY)) ? AsyncHttpFetch::RESULT_PARTIAL_BODY :
                                                                                        AsyncHttpFetch::RESULT_BODY_COMPLETE;
    }
  }
  if (!state->dispatch_controller_->dispatch()) {
    LOG_DEBUG("Unable to dispatch result from AsyncFetch because promise has died.");
  }

  if ((state->streaming_flag_ == AsyncHttpFetch::STREAMING_DISABLED) || (state->result_ == AsyncHttpFetch::RESULT_BODY_COMPLETE)) {
    LOG_DEBUG("Shutting down");
    utils::internal::deleteAsyncHttpFetch(fetch_provider); // we must always cleans up when we're done.
    TSContDestroy(cont);
  }
  return 0;
}
} // namespace

AsyncHttpFetch::AsyncHttpFetch(const string &url_str, const string &request_body)
{
  init(url_str, HTTP_METHOD_POST, request_body, STREAMING_DISABLED);
}

AsyncHttpFetch::AsyncHttpFetch(const string &url_str, HttpMethod http_method)
{
  init(url_str, http_method, "", STREAMING_DISABLED);
}

AsyncHttpFetch::AsyncHttpFetch(const string &url_str, StreamingFlag streaming_flag, const string &request_body)
{
  init(url_str, HTTP_METHOD_POST, request_body, streaming_flag);
}

AsyncHttpFetch::AsyncHttpFetch(const string &url_str, StreamingFlag streaming_flag, HttpMethod http_method)
{
  init(url_str, http_method, "", streaming_flag);
}

void
AsyncHttpFetch::init(const string &url_str, HttpMethod http_method, const string &request_body, StreamingFlag streaming_flag)
{
  LOG_DEBUG("Created new AsyncHttpFetch object %p", this);
  state_ = std::make_unique<AsyncHttpFetchState>(url_str, http_method, request_body, streaming_flag);
}

void
AsyncHttpFetch::run()
{
  state_->dispatch_controller_ = getDispatchController(); // keep a copy in state so that cont handler can use it

  TSCont fetchCont = TSContCreate(handleFetchEvents, TSMutexCreate());
  TSContDataSet(fetchCont, static_cast<void *>(this)); // Providers have to clean themselves up when they are done.

  struct sockaddr_in addr;
  addr.sin_family      = AF_INET;
  addr.sin_addr.s_addr = LOCAL_IP_ADDRESS;
  addr.sin_port        = LOCAL_PORT;

  Headers &headers = state_->request_->getHeaders();
  if (headers.size()) {
    // remove the possibility of keep-alive
    headers.erase("Connection");
    headers.erase("Proxy-Connection");
  }
  if (!state_->request_body_.empty()) {
    char size_buf[128];
    snprintf(size_buf, sizeof(size_buf), "%zu", state_->request_body_.size());
    headers.set("Content-Length", size_buf);
  }

  if (state_->streaming_flag_ == STREAMING_DISABLED) {
    TSFetchEvent event_ids;
    event_ids.success_event_id = RESULT_SUCCESS;
    event_ids.failure_event_id = RESULT_FAILURE;
    event_ids.timeout_event_id = RESULT_TIMEOUT;

    string request_str(HTTP_METHOD_STRINGS[state_->request_->getMethod()]);
    request_str += ' ';
    request_str += state_->request_->getUrl().getUrlString();
    request_str += ' ';
    request_str += HTTP_VERSION_STRINGS[state_->request_->getVersion()];
    request_str += "\r\n";
    request_str += headers.wireStr();
    request_str += "\r\n";
    request_str += state_->request_body_;

    LOG_DEBUG("Issuing (non-streaming) TSFetchUrl with request\n[%s]", request_str.c_str());
    TSFetchUrl(request_str.c_str(), request_str.size(), reinterpret_cast<struct sockaddr const *>(&addr), fetchCont, AFTER_BODY,
               event_ids);
  } else {
    state_->fetch_sm_ =
      TSFetchCreate(fetchCont, HTTP_METHOD_STRINGS[state_->request_->getMethod()].c_str(),
                    state_->request_->getUrl().getUrlString().c_str(), HTTP_VERSION_STRINGS[state_->request_->getVersion()].c_str(),
                    reinterpret_cast<struct sockaddr const *>(&addr), TS_FETCH_FLAGS_STREAM | TS_FETCH_FLAGS_DECHUNK);
    string header_value;
    for (auto &&header : headers) {
      HeaderFieldName header_name = header.name();
      header_value                = header.values();
      TSFetchHeaderAdd(state_->fetch_sm_, header_name.c_str(), header_name.length(), header_value.data(), header_value.size());
    }
    LOG_DEBUG("Launching streaming fetch");
    TSFetchLaunch(state_->fetch_sm_);
    if (state_->request_body_.size()) {
      TSFetchWriteData(state_->fetch_sm_, state_->request_body_.data(), state_->request_body_.size());
      LOG_DEBUG("Wrote %zu bytes of data to fetch", state_->request_body_.size());
    }
  }
}

Headers &
AsyncHttpFetch::getRequestHeaders()
{
  return state_->request_->getHeaders();
}

AsyncHttpFetch::Result
AsyncHttpFetch::getResult() const
{
  return state_->result_;
}

const Url &
AsyncHttpFetch::getRequestUrl() const
{
  return state_->request_->getUrl();
}

const string &
AsyncHttpFetch::getRequestBody() const
{
  return state_->request_body_;
}

const Response &
AsyncHttpFetch::getResponse() const
{
  return state_->response_;
}

void
AsyncHttpFetch::getResponseBody(const void *&body, size_t &body_size) const
{
  body      = state_->body_;
  body_size = state_->body_size_;
}

AsyncHttpFetch::~AsyncHttpFetch() {}
