/*
    This file is part of TON Blockchain Library.
    TON Blockchain Library is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 2 of the License, or
    (at your option) any later version.
    TON Blockchain Library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.
    You should have received a copy of the GNU Lesser General Public License
    along with TON Blockchain Library.  If not, see .
    Copyright 2019-2020 Telegram Systems LLP
*/
#include "http-client.hpp"
#include "td/utils/Random.h"
namespace ton {
namespace http {
void HttpClientImpl::create_connection() {
  alarm_timestamp().relax(td::Timestamp::in(td::Random::fast(10.0, 20.0)));
  if (domain_.size() > 0) {
    auto S = addr_.init_host_port(domain_);
    if (S.is_error()) {
      LOG(INFO) << "failed domain '" << domain_ << "': " << S;
      return;
    }
  }
  auto fd = td::SocketFd::open(addr_);
  if (fd.is_error()) {
    LOG(INFO) << "failed to connect to " << addr_ << ": " << fd.move_as_error();
    return;
  }
  class Cb : public HttpClient::Callback {
   public:
    Cb(td::actor::ActorId id) : id_(id) {
    }
    void on_ready() override {
      td::actor::send_closure(id_, &HttpClientImpl::client_ready, true);
    }
    void on_stop_ready() override {
      td::actor::send_closure(id_, &HttpClientImpl::client_ready, false);
    }
   private:
    td::actor::ActorId id_;
  };
  conn_ = td::actor::create_actor(td::actor::ActorOptions().with_name("outconn").with_poll(),
                                                          fd.move_as_ok(), std::make_shared(actor_id(this)));
}
void HttpClientImpl::send_request(
    std::unique_ptr request, std::shared_ptr payload, td::Timestamp timeout,
    td::Promise, std::shared_ptr>> promise) {
  td::actor::send_closure(conn_, &HttpOutboundConnection::send_query, std::move(request), std::move(payload), timeout,
                          std::move(promise));
}
void HttpMultiClientImpl::send_request(
    std::unique_ptr request, std::shared_ptr payload, td::Timestamp timeout,
    td::Promise, std::shared_ptr>> promise) {
  if (domain_.size() > 0) {
    auto S = addr_.init_host_port(domain_);
    if (S.is_error()) {
      return answer_error(HttpStatusCode::status_bad_gateway, "", std::move(promise));
    }
  }
  auto fd = td::SocketFd::open(addr_);
  if (fd.is_error()) {
    return answer_error(HttpStatusCode::status_bad_gateway, "", std::move(promise));
  }
  class Cb : public HttpClient::Callback {
   public:
    Cb(td::actor::ActorId id) : id_(id) {
    }
    void on_ready() override {
    }
    void on_stop_ready() override {
    }
   private:
    td::actor::ActorId id_;
  };
  auto conn =
      td::actor::create_actor(td::actor::ActorOptions().with_name("outconn").with_poll(),
                                                      fd.move_as_ok(), std::make_shared(actor_id(this)))
          .release();
  request->set_keep_alive(false);
  td::actor::send_closure(conn, &HttpOutboundConnection::send_query, std::move(request), std::move(payload), timeout,
                          std::move(promise));
}
td::actor::ActorOwn HttpClient::create(std::string domain, td::IPAddress addr,
                                                   std::shared_ptr callback) {
  return td::actor::create_actor("httpclient", std::move(domain), addr, std::move(callback));
}
td::actor::ActorOwn HttpClient::create_multi(std::string domain, td::IPAddress addr,
                                                         td::uint32 max_connections,
                                                         td::uint32 max_requests_per_connect,
                                                         std::shared_ptr callback) {
  return td::actor::create_actor("httpmclient", std::move(domain), addr, max_connections,
                                                      max_requests_per_connect, std::move(callback));
}
}  // namespace http
}  // namespace ton