// Copyright 2019 Google LLC
//
// 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 "socket.h"

#if defined(_WIN32)
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <netdb.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <unistd.h>
#endif

#if defined(_WIN32)
#include <atomic>
namespace {
std::atomic<int> wsaInitCount = {0};
}  // anonymous namespace
#else
namespace {
using SOCKET = int;
}  // anonymous namespace
#endif

namespace {
constexpr SOCKET InvalidSocket = static_cast<SOCKET>(-1);
}  // anonymous namespace

class dap::Socket::Shared : public dap::ReaderWriter {
 public:
  static void init() {
#if defined(_WIN32)
    if (wsaInitCount++ == 0) {
      WSADATA winsockData;
      (void)WSAStartup(MAKEWORD(2, 2), &winsockData);
    }
#endif
  }

  static void term() {
#if defined(_WIN32)
    if (--wsaInitCount == 0) {
      WSACleanup();
    }
#endif
  }

  static std::shared_ptr<Shared> create(const char* address, const char* port) {
    init();

    addrinfo hints = {};
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;

    addrinfo* info = nullptr;
    getaddrinfo(address, port, &hints, &info);

    if (info) {
      auto socket =
          ::socket(info->ai_family, info->ai_socktype, info->ai_protocol);
      return std::make_shared<Shared>(*info, socket);
    }

    term();
    return nullptr;
  }

  Shared(SOCKET socket) : info({}), sock(socket) {}
  Shared(const addrinfo& info, SOCKET socket) : info(info), sock(socket) {}

  ~Shared() {
    close();
    term();
  }

  SOCKET socket() { return sock.load(); }

  // dap::ReaderWriter compliance
  bool isOpen() {
    SOCKET s = socket();
    if (s == InvalidSocket) {
      return false;
    }

    char error = 0;
    socklen_t len = sizeof(error);
    getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len);
    if (error != 0) {
      sock.compare_exchange_weak(s, InvalidSocket);
      return false;
    }

    return true;
  }

  void close() {
    SOCKET s = sock.exchange(InvalidSocket);
    if (s != InvalidSocket) {
#if defined(_WIN32)
      closesocket(s);
#else
      ::shutdown(s, SHUT_RDWR);
      ::close(s);
#endif
    }
  }

  size_t read(void* buffer, size_t bytes) {
    SOCKET s = socket();
    if (s == InvalidSocket) {
      return 0;
    }
    return recv(s, reinterpret_cast<char*>(buffer), static_cast<int>(bytes), 0);
  }

  bool write(const void* buffer, size_t bytes) {
    SOCKET s = socket();
    if (s == InvalidSocket) {
      return false;
    }
    if (bytes == 0) {
      return true;
    }
    return ::send(s, reinterpret_cast<const char*>(buffer),
                  static_cast<int>(bytes), 0) > 0;
  }

  const addrinfo info;

 private:
  std::atomic<SOCKET> sock = {InvalidSocket};
};

namespace dap {

Socket::Socket(const char* address, const char* port)
    : shared(Shared::create(address, port)) {
  if (!shared) {
    return;
  }
  auto socket = shared->socket();

  if (bind(socket, shared->info.ai_addr, (int)shared->info.ai_addrlen) != 0) {
    shared.reset();
    return;
  }

  if (listen(socket, 1) != 0) {
    shared.reset();
    return;
  }
}

std::shared_ptr<ReaderWriter> Socket::accept() const {
  if (shared) {
    SOCKET socket = shared->socket();
    if (socket != InvalidSocket) {
      return std::make_shared<Shared>(::accept(socket, 0, 0));
    }
  }

  return {};
}

bool Socket::isOpen() const {
  if (shared) {
    return shared->isOpen();
  }
  return false;
}

void Socket::close() const {
  if (shared) {
    shared->close();
  }
}

std::shared_ptr<ReaderWriter> Socket::connect(const char* address,
                                              const char* port) {
  auto shared = Shared::create(address, port);
  if (::connect(shared->socket(), shared->info.ai_addr,
                (int)shared->info.ai_addrlen) == 0) {
    return shared;
  }
  return {};
}

}  // namespace dap
