#include <raylib.h>

#include <string>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <fstream>
#include <cstring>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

#define PORT 8080
#define BUFFER_SIZE 1024

struct in_addr ipAddr;
bool resolved = false;

bool resolveDNS()
{
  const char *host = "petrovv.com";
  struct addrinfo hints{}, *res, *p;

  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
  hints.ai_socktype = SOCK_STREAM;

  int status = getaddrinfo(host, nullptr, &hints, &res);
  if (status != 0)
  {
    return false;
  }

  for (p = res; p != nullptr; p = p->ai_next)
  {

    if (p->ai_family == AF_INET)
    { // IPv4
      auto *ipv4 = (struct sockaddr_in *)p->ai_addr;
      ipAddr = ipv4->sin_addr;
      resolved = true;
    }

    break; // Just take the first address
  }
  freeaddrinfo(res);
  return true;
}

int sendFile()
{
  int sock = 0;
  struct sockaddr_in serv_addr;
  char buffer[BUFFER_SIZE] = {0};
  std::ifstream file("example.txt", std::ios::binary);

  if (!file)
  {
    // std::cerr << "Unable to open file" << std::endl;
    TraceLog(LOG_ERROR, "Unable to open file");
    return 1;
  }

  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  {
    TraceLog(LOG_ERROR, "Socket creation error");
    return 1;
  }

  serv_addr.sin_family = AF_INET;
  serv_addr.sin_port = htons(PORT);

  // Convert IPv4 and IPv6 addresses from text to binary form
  if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0)
  {
    TraceLog(LOG_ERROR, "Invalid address/ Address not supported");
    return 1;
  }

  if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
  {
    TraceLog(LOG_ERROR, "Connection Failed");
    return 1;
  }

  while (file.read(buffer, BUFFER_SIZE))
  {
    send(sock, buffer, file.gcount(), 0);
  }

  // Send the remaining bytes if the file size is not a multiple of BUFFER_SIZE
  send(sock, buffer, file.gcount(), 0);

  TraceLog(LOG_INFO, "File sent successfully");

  close(sock);
  file.close();
  return 0;
}

int sendBuffer()
{
  if (!resolved)
    return 1;
  int sock = 0;
  struct sockaddr_in serv_addr;
  char buffer[BUFFER_SIZE] = {123, 123, 123};

  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  {
    TraceLog(LOG_ERROR, "Socket creation error");
    return 1;
  }

  serv_addr.sin_family = AF_INET;
  serv_addr.sin_port = htons(PORT);
  serv_addr.sin_addr = ipAddr;

  // Convert IPv4 and IPv6 addresses from text to binary form
  // if (inet_pton(AF_INET, "192.168.0.31", &serv_addr.sin_addr) <= 0)
  // {
  //   TraceLog(LOG_ERROR, "Invalid address/ Address not supported");
  //   return 1;
  // }

  if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
  {
    TraceLog(LOG_ERROR, "Connection Failed");
    return 1;
  }

  send(sock, buffer, 3, 0);

  TraceLog(LOG_INFO, "File sent successfully");

  close(sock);

  return 0;
}