// Copyright 2023 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 "pw_data_link/socket_data_link.h"

#if defined(_WIN32) && _WIN32
// TODO(cachinchilla): add support for windows.
#error Windows not supported yet!
#else
#include <arpa/inet.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#endif  // defined(_WIN32) && _WIN32

#include <chrono>
#include <optional>

#include "pw_allocator/allocator.h"
#include "pw_assert/check.h"
#include "pw_bytes/span.h"
#include "pw_log/log.h"
#include "pw_multibuf/chunk_region_tracker.h"
#include "pw_status/status.h"
#include "pw_status/status_with_size.h"

namespace pw::data_link {
namespace {

const char* kLinkStateNameOpen = "Open";
const char* kLinkStateNameOpenRequest = "Open Request";
const char* kLinkStateNameClosed = "Closed";
const char* kLinkStateNameWaitingForOpen = "Waiting For Open";
const char* kLinkStateNameUnknown = "Unknown";
const auto kEpollTimeout = std::chrono::seconds(1);

// Configures the file descriptor as non blocking. Returns true when successful.
bool MakeSocketNonBlocking(int fd) {
  int flags = fcntl(fd, F_GETFL, 0);
  if (flags == -1) {
    return false;
  }
  flags += O_NONBLOCK;
  if (fcntl(fd, F_SETFL, flags) == -1) {
    PW_LOG_ERROR("Failed to create a socket: %s", std::strerror(errno));
    return false;
  }
  return true;
}

}  // namespace

SocketDataLink::SocketDataLink(const char* host, uint16_t port) : host_(host) {
  PW_CHECK(host_ != nullptr);
  PW_CHECK(ToString(port, port_).ok());
}

SocketDataLink::SocketDataLink(int connection_fd,
                               EventHandlerCallback&& event_handler,
                               allocator::Allocator& write_buffer_allocator)
    : connection_fd_(connection_fd),
      write_buffer_allocator_(&write_buffer_allocator) {
  PW_DCHECK(connection_fd > 0);
  PW_CHECK(MakeSocketNonBlocking(connection_fd_));
  PW_CHECK(ConfigureEpoll());
  event_handler_ = std::move(event_handler);
  set_link_state(LinkState::kOpen);
  write_state_ = WriteState::kIdle;
  read_state_ = ReadState::kIdle;
  event_handler_(DataLink::Event::kOpen, StatusWithSize());
}

SocketDataLink::~SocketDataLink() {
  lock_.lock();
  if (link_state_ != LinkState::kClosed) {
    DoClose(/*notify_closed=*/true);
    return;
  }
  lock_.unlock();
}

void SocketDataLink::set_link_state(LinkState new_state) {
  const char* link_name;
  switch (link_state_) {
    case LinkState::kOpen:
      link_name = kLinkStateNameOpen;
      break;
    case LinkState::kOpenRequest:
      link_name = kLinkStateNameOpenRequest;
      break;
    case LinkState::kClosed:
      link_name = kLinkStateNameClosed;
      break;
    case LinkState::kWaitingForOpen:
      link_name = kLinkStateNameWaitingForOpen;
      break;
    default:
      link_name = kLinkStateNameUnknown;
  };

  const char* new_link_name;
  switch (new_state) {
    case LinkState::kOpen:
      new_link_name = kLinkStateNameOpen;
      break;
    case LinkState::kOpenRequest:
      new_link_name = kLinkStateNameOpenRequest;
      break;
    case LinkState::kClosed:
      new_link_name = kLinkStateNameClosed;
      break;
    case LinkState::kWaitingForOpen:
      new_link_name = kLinkStateNameWaitingForOpen;
      break;
    default:
      new_link_name = kLinkStateNameUnknown;
  };
  PW_LOG_DEBUG("Transitioning from %s to %s", link_name, new_link_name);
  link_state_ = new_state;
}

void SocketDataLink::Open(EventHandlerCallback&& event_handler,
                          allocator::Allocator& write_buffer_allocator) {
  std::lock_guard lock(lock_);
  PW_CHECK(link_state_ == LinkState::kClosed);

  write_buffer_allocator_ = &write_buffer_allocator;
  event_handler_ = std::move(event_handler);
  set_link_state(LinkState::kOpenRequest);
}

void SocketDataLink::WaitAndConsumeEvents() {
  // Manually lock and unlock, since some functions may perform unlocking before
  // calling the user's event callback, when locks cannot be held.

  lock_.lock();
  switch (link_state_) {
    case LinkState::kOpen:
      break;
    case LinkState::kWaitingForOpen: {
      // Copy the epoll file descriptor to reduce the critical section.
      const int fd = epoll_fd_;
      lock_.unlock();
      epoll_event event;
      const int count = epoll_wait(
          fd, &event, 1, std::chrono::milliseconds(kEpollTimeout).count());
      if (count == 0) {
        return;
      }
      if (event.events & EPOLLERR || event.events & EPOLLHUP) {
        lock_.lock();
        // Check if link was closed on another thread.
        if (link_state_ != LinkState::kClosed) {
          DoClose(/*notify_closed=*/false);
        } else {
          lock_.unlock();
        }
        event_handler_(DataLink::Event::kOpen, StatusWithSize::Unknown());
        return;
      }
      if (event.events == EPOLLOUT) {
        {
          std::lock_guard lock(lock_);
          set_link_state(LinkState::kOpen);
        }
        {
          std::lock_guard lock(write_lock_);
          write_state_ = WriteState::kIdle;
        }
        {
          std::lock_guard lock(read_lock_);
          read_state_ = ReadState::kIdle;
        }
        event_handler_(DataLink::Event::kOpen, StatusWithSize());
        return;
      }
      PW_LOG_ERROR("Unhandled event %d while waiting to open link",
                   static_cast<int>(event.events));
    }
      return;
    case LinkState::kClosed:
      lock_.unlock();
      return;
    case LinkState::kOpenRequest:
      DoOpen();
      return;
  }
  // Copy the epoll file descriptor to reduce the critical section.
  const int fd = epoll_fd_;
  lock_.unlock();

  epoll_event event;
  const int count = epoll_wait(
      fd, &event, 1, std::chrono::milliseconds(kEpollTimeout).count());
  if (count == 0) {
    return;
  }

  if (event.events & EPOLLERR || event.events & EPOLLHUP) {
    lock_.lock();
    // Check if link was closed on another thread.
    if (link_state_ != LinkState::kClosed) {
      DoClose(/*notify_closed=*/true);
    } else {
      lock_.unlock();
    }
    return;
  }

  if (event.events & EPOLLIN) {
    // Can read!
    read_lock_.lock();
    if (read_state_ == ReadState::kReadRequested) {
      DoRead();
    } else if (read_state_ == ReadState::kIdle) {
      read_lock_.unlock();
      event_handler_(DataLink::Event::kDataReceived, StatusWithSize());
    } else {
      read_lock_.unlock();
    }
  }
  if (event.events & EPOLLOUT) {
    // Can Write!
    write_lock_.lock();
    if (write_state_ == WriteState::kPending) {
      DoWrite();
    } else {
      write_lock_.unlock();
    }
  }
  if ((event.events & EPOLLIN) == 0 && (event.events & EPOLLOUT) == 0) {
    PW_LOG_WARN("Unhandled event %d", static_cast<int>(event.events));
  }
}

void SocketDataLink::DoOpen() {
  addrinfo hints = {};
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_NUMERICSERV;
  addrinfo* res;
  if (getaddrinfo(host_, port_, &hints, &res) != 0) {
    PW_LOG_ERROR("Failed to configure connection address for socket");
    HandleOpenFailure(/*info=*/nullptr);
    return;
  }

  addrinfo* rp;
  for (rp = res; rp != nullptr; rp = rp->ai_next) {
    PW_LOG_DEBUG("Opening socket");
    connection_fd_ = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
    if (connection_fd_ != kInvalidFd) {
      break;
    }
  }
  if (connection_fd_ == kInvalidFd) {
    HandleOpenFailure(res);
    return;
  }
  // Set necessary options on a socket file descriptor.
  PW_LOG_DEBUG("Configuring socket");
  if (!MakeSocketNonBlocking(connection_fd_)) {
    HandleOpenFailure(res);
    return;
  }
  PW_LOG_DEBUG("Connecting socket");
  if (connect(connection_fd_, rp->ai_addr, rp->ai_addrlen) == -1) {
    if (errno != EINPROGRESS) {
      HandleOpenFailure(res);
      return;
    }
    set_link_state(LinkState::kWaitingForOpen);
  } else {
    set_link_state(LinkState::kOpen);
  }

  PW_LOG_DEBUG("Configuring Epoll");
  if (!ConfigureEpoll()) {
    HandleOpenFailure(res);
    return;
  }
  const bool open_completed = link_state_ == LinkState::kOpen;
  lock_.unlock();
  freeaddrinfo(res);
  if (open_completed) {
    {
      std::lock_guard lock(write_lock_);
      write_state_ = WriteState::kIdle;
    }
    {
      std::lock_guard lock(read_lock_);
      read_state_ = ReadState::kIdle;
    }
    event_handler_(DataLink::Event::kOpen, StatusWithSize());
  }
}

void SocketDataLink::HandleOpenFailure(addrinfo* info) {
  if (connection_fd_ != kInvalidFd) {
    close(connection_fd_);
    connection_fd_ = kInvalidFd;
  }
  if (epoll_fd_ != kInvalidFd) {
    close(epoll_fd_);
    epoll_fd_ = kInvalidFd;
  }
  set_link_state(LinkState::kClosed);
  lock_.unlock();
  PW_LOG_ERROR(
      "Failed to connect to %s:%s: %s", host_, port_, std::strerror(errno));
  if (info != nullptr) {
    freeaddrinfo(info);
  }
  event_handler_(DataLink::Event::kOpen, StatusWithSize::Unknown());
}

bool SocketDataLink::ConfigureEpoll() {
  epoll_fd_ = epoll_create1(0);
  if (epoll_fd_ == kInvalidFd) {
    return false;
  }
  epoll_event_.events = EPOLLOUT | EPOLLIN;
  epoll_event_.data.fd = connection_fd_;
  if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, connection_fd_, &epoll_event_) ==
      -1) {
    return false;
  }
  return true;
}

void SocketDataLink::Close() {
  lock_.lock();
  PW_DCHECK(link_state_ != LinkState::kClosed);
  DoClose(/*notify_closed=*/true);
}

void SocketDataLink::DoClose(bool notify_closed) {
  set_link_state(LinkState::kClosed);
  // Copy file descriptors and unlock to minimize the critical section.
  const int connection_fd = connection_fd_;
  connection_fd_ = kInvalidFd;
  const int epoll_fd = epoll_fd_;
  epoll_fd_ = kInvalidFd;
  lock_.unlock();
  {
    std::lock_guard lock(write_lock_);
    write_state_ = WriteState::kClosed;
  }
  {
    std::lock_guard lock(read_lock_);
    read_state_ = ReadState::kClosed;
  }

  // Close file descriptors if valid.
  if (connection_fd != kInvalidFd) {
    close(connection_fd);
  }
  if (epoll_fd != kInvalidFd) {
    close(epoll_fd);
  }
  if (notify_closed) {
    event_handler_(DataLink::Event::kClosed, StatusWithSize());
  }
}

std::optional<multibuf::MultiBuf> SocketDataLink::GetWriteBuffer(size_t size) {
  if (size == 0) {
    return multibuf::MultiBuf();
  }
  {
    std::lock_guard lock(write_lock_);
    if (write_state_ != WriteState::kIdle) {
      return std::nullopt;
    }
  }
  multibuf::MultiBuf buffer;
  std::optional<multibuf::OwnedChunk> chunk =
      multibuf::HeaderChunkRegionTracker::AllocateRegionAsChunk(
          write_buffer_allocator_, size);
  if (!chunk) {
    return std::nullopt;
  }
  buffer.PushFrontChunk(std::move(*chunk));
  return buffer;
}

Status SocketDataLink::Write(multibuf::MultiBuf&& buffer) {
  if (buffer.size() == 0) {
    return Status::InvalidArgument();
  }
  std::lock_guard lock(write_lock_);
  if (write_state_ != WriteState::kIdle) {
    return Status::FailedPrecondition();
  }

  tx_multibuf_ = std::move(buffer);
  num_bytes_to_send_ = tx_multibuf_.size();
  num_bytes_sent_ = 0;
  write_state_ = WriteState::kPending;
  return OkStatus();
}

void SocketDataLink::DoWrite() {
  int send_flags = 0;
#if defined(__linux__)
  // Use MSG_NOSIGNAL to avoid getting a SIGPIPE signal when the remote
  // peer drops the connection. This is supported on Linux only.
  send_flags |= MSG_NOSIGNAL;
#endif  // defined(__linux__)

  auto [chunk_iter, chunk] =
      tx_multibuf_.TakeChunk(tx_multibuf_.Chunks().begin());
  ssize_t bytes_sent;
  {
    std::lock_guard lock(lock_);
    // TODO: Send one chunk at a time.
    bytes_sent = send(connection_fd_,
                      reinterpret_cast<const char*>(chunk.data()),
                      chunk.size(),
                      send_flags);
  }

  // Check for errors.
  if (bytes_sent < 0) {
    if (errno == EPIPE) {
      // An EPIPE indicates that the connection is closed.
      tx_multibuf_.Release();
      write_lock_.unlock();
      event_handler_(DataLink::Event::kDataSent, StatusWithSize::OutOfRange());
      Close();
      return;
    }
    tx_multibuf_.Release();
    write_lock_.unlock();
    event_handler_(DataLink::Event::kDataSent, StatusWithSize::Unknown());
    return;
  }
  num_bytes_sent_ += bytes_sent;

  // Resize chunk if it was a partial write.
  if (static_cast<size_t>(bytes_sent) < chunk.size()) {
    chunk->DiscardFront(static_cast<size_t>(bytes_sent));
    tx_multibuf_.PushFrontChunk(std::move(chunk));
    write_lock_.unlock();
    return;
  }

  // Check if we are done with the MultiBuf.
  if (num_bytes_sent_ >= num_bytes_to_send_) {
    write_state_ = WriteState::kIdle;
    tx_multibuf_.Release();
    write_lock_.unlock();
    event_handler_(DataLink::Event::kDataSent,
                   StatusWithSize(num_bytes_to_send_));
    return;
  }

  write_lock_.unlock();
}

Status SocketDataLink::Read(ByteSpan buffer) {
  PW_DCHECK(buffer.size() > 0);
  std::lock_guard lock(read_lock_);
  if (read_state_ != ReadState::kIdle) {
    return Status::FailedPrecondition();
  }
  rx_buffer_ = buffer;
  read_state_ = ReadState::kReadRequested;
  return OkStatus();
}

void SocketDataLink::DoRead() {
  ssize_t bytes_rcvd;
  {
    std::lock_guard lock(lock_);
    bytes_rcvd = recv(connection_fd_,
                      reinterpret_cast<char*>(rx_buffer_.data()),
                      rx_buffer_.size_bytes(),
                      0);
  }

  if (bytes_rcvd == 0) {
    // Remote peer has closed the connection.
    read_state_ = ReadState::kClosed;
    read_lock_.unlock();
    event_handler_(DataLink::Event::kDataRead, StatusWithSize::Internal());
    Close();
    return;
  } else if (bytes_rcvd < 0) {
    if (errno == EAGAIN || errno == EWOULDBLOCK) {
      // Socket timed out when trying to read.
      // This should only occur if SO_RCVTIMEO was configured to be nonzero, or
      // if the socket was opened with the O_NONBLOCK flag to prevent any
      // blocking when performing reads or writes.
      read_state_ = ReadState::kIdle;
      read_lock_.unlock();
      event_handler_(DataLink::Event::kDataRead,
                     StatusWithSize::ResourceExhausted());
      return;
    }
    read_state_ = ReadState::kIdle;
    read_lock_.unlock();
    event_handler_(DataLink::Event::kDataRead, StatusWithSize::Unknown());
    return;
  }
  read_state_ = ReadState::kIdle;
  read_lock_.unlock();
  event_handler_(DataLink::Event::kDataRead, StatusWithSize(bytes_rcvd));
}

}  // namespace pw::data_link
