// Copyright 2021 The Pigweed Authors
//
// Licensed 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
//
//     https://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 "mbedtls/ssl.h"
#include "pw_assert/check.h"
#include "pw_log/log.h"
#include "pw_tls_client/entropy.h"
#include "pw_tls_client/session.h"
#include "pw_tls_client_mbedtls/backend_types.h"

namespace pw::tls_client {
namespace backend {

int SessionImplementation::MbedTlsWrite(void* ctx,
                                        const uint8_t* buf,
                                        size_t len) {
  PW_CHECK_NOTNULL(ctx);
  PW_CHECK_NOTNULL(buf);
  auto writer =
      static_cast<SessionImplementation*>(ctx)->session_options_.transport();
  PW_CHECK_NOTNULL(writer);
  return writer->Write(buf, len).ok() ? len : -1;
}

int SessionImplementation::MbedTlsRead(void* ctx,
                                       unsigned char* buf,
                                       size_t len) {
  PW_CHECK_NOTNULL(ctx);
  PW_CHECK_NOTNULL(buf);
  auto reader =
      static_cast<SessionImplementation*>(ctx)->session_options_.transport();
  PW_CHECK_NOTNULL(reader);
  auto res = reader->Read(buf, len);
  if (!res.ok()) {
    return -1;
  }
  return res.value().empty() ? MBEDTLS_ERR_SSL_WANT_READ : res.value().size();
}

Status SessionImplementation::entropy_source_status_ = OkStatus();

void SessionImplementation::SetEntropySourceStatus(Status status) {
  entropy_source_status_ = status;
}

// Entropy source callback
int SessionImplementation::MbedTlsEntropySource(void* ctx,
                                                unsigned char* out,
                                                size_t len,
                                                size_t* output_length) {
  Status status;
  if (entropy_source_status_ != OkStatus()) {
    status = entropy_source_status_;
  } else {
    status = GetRandomBytes({out, len});
  }

  if (!status.ok()) {
    PW_LOG_DEBUG("Failed to generate random bytes");
    auto session_impl = static_cast<SessionImplementation*>(ctx);
    session_impl->SetTlsStatus(pw::tls_client::TLSStatus::kEntropySourceFailed);
    return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
  }
  *output_length = len;
  return 0;
}

SessionImplementation::SessionImplementation(SessionOptions options)
    : session_options_(options) {
  mbedtls_ssl_init(&ssl_ctx_);
  mbedtls_ssl_config_init(&ssl_config_);
  mbedtls_ctr_drbg_init(&drbg_ctx_);
  mbedtls_entropy_init(&entropy_ctx_);
}

SessionImplementation::~SessionImplementation() {
  mbedtls_ssl_free(&ssl_ctx_);
  mbedtls_ssl_config_free(&ssl_config_);
  mbedtls_ctr_drbg_free(&drbg_ctx_);
  mbedtls_entropy_free(&entropy_ctx_);
}

Status SessionImplementation::Setup() {
  int ret = 0;

  // Set up default configuration.
  ret = mbedtls_ssl_config_defaults(
      &ssl_config_,
      // Configured as client.
      MBEDTLS_SSL_IS_CLIENT,
      // Statndard TLS. The other option is MBEDTLS_SSL_TRANSPORT_DATAGRAM
      // for DTLS, which we'll consider later.
      MBEDTLS_SSL_TRANSPORT_STREAM,
      // This option is used in all MbedTLS native examples.
      // The other option is MBEDTLS_SSL_PRESET_SUITEB.
      // However, there is no document/comment availalbe on what they do.
      // Base on the source code, these options will restrict the version
      // of TLS protocol. MBEDTLS_SSL_PRESET_SUITEB forces TLS 1.2.
      // MBEDTLS_SSL_PRESET_DEFAULT is more relaxed. But since we
      // define MBEDTLS_SSL_PROTO_TLS1_2 for all configs. There shouldn't be
      // any difference.
      MBEDTLS_SSL_PRESET_DEFAULT);
  if (ret) {
    return Status::Internal();
  }

  // Set up an entropy source.
  ret = mbedtls_entropy_add_source(&entropy_ctx_,
                                   MbedTlsEntropySource,
                                   this,
                                   1,
                                   MBEDTLS_ENTROPY_SOURCE_STRONG);
  if (ret) {
    return Status::Internal();
  }

  // Set up drbg.
  unsigned char personalized_bytes[] = "pw_tls_client";
  ret = mbedtls_ctr_drbg_seed(&drbg_ctx_,
                              mbedtls_entropy_func,
                              &entropy_ctx_,
                              personalized_bytes,
                              sizeof(personalized_bytes));
  if (ret) {
    if (ret == MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) {
      tls_status_ = TLSStatus::kEntropySourceFailed;
    }
    return Status::Internal();
  }

  // The API does not fail.
  mbedtls_ssl_conf_rng(&ssl_config_, mbedtls_ctr_drbg_random, &drbg_ctx_);

  // The API does not fail.
  mbedtls_ssl_conf_authmode(&ssl_config_, MBEDTLS_SSL_VERIFY_REQUIRED);

  // TODO(b/235289501): Add logic for loading trust anchors.

  // Load configuration to SSL.
  ret = mbedtls_ssl_setup(&ssl_ctx_, &ssl_config_);
  if (ret) {
    return Status::Internal();
  }

  // Set up transport.
  // The API does not fail.
  mbedtls_ssl_set_bio(&ssl_ctx_, this, MbedTlsWrite, MbedTlsRead, nullptr);

  ret = mbedtls_ssl_set_hostname(&ssl_ctx_,
                                 session_options_.server_name().data());
  if (ret) {
    return Status::Internal();
  }

  return OkStatus();
}

}  // namespace backend

Session::Session(const SessionOptions& options) : session_impl_(options) {}

Session::~Session() = default;

Result<Session*> Session::Create(const SessionOptions& options) {
  if (!options.transport()) {
    PW_LOG_DEBUG("Must provide a transport");
    return Status::Internal();
  }

  auto sess = new Session(options);
  if (!sess) {
    return Status::ResourceExhausted();
  }

  // Set up the client.
  auto setup_status = sess->session_impl_.Setup();
  if (!setup_status.ok()) {
    PW_LOG_DEBUG("Failed to setup");
    // TODO(b/235289501): `tls_status_` may be set, but the session object will
    // be released. Map `tls_stauts_` to string and print out here so that
    // the information can be catched.
    delete sess;
    return setup_status;
  }

  return sess;
}

Status Session::Open() {
  // TODO(b/235289501): To implement
  return Status::Unimplemented();
}

Status Session::Close() {
  // TODO(b/235289501): To implement
  return Status::Unimplemented();
}

StatusWithSize Session::DoRead(ByteSpan) {
  // TODO(b/235289501): To implement
  return StatusWithSize(Status::Unimplemented(), 0);
}

Status Session::DoWrite(ConstByteSpan) {
  // TODO(b/235289501): To implement
  return Status::Unimplemented();
}

TLSStatus Session::GetLastTLSStatus() { return session_impl_.GetTlsStatus(); }

}  // namespace pw::tls_client
