#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <winsock2.h>
#include <vector>
#include <thread>
#include <algorithm> // For std::remove

#pragma comment(lib, "ws2_32.lib")

std::vector<SOCKET> clients;

void BroadcastMessage(const std::string& message, SOCKET sender) {
    for (SOCKET client : clients) {
        if (client != sender) { // Don't send the message back to the sender
            send(client, message.c_str(), message.length(), 0);
        }
    }
}

void ClientHandler(SOCKET clientSocket) {
    char buffer[1024];
    while (true) {
        ZeroMemory(buffer, sizeof(buffer)); // Clear buffer before receiving

        // Receive message from client
        int bytesReceived = recv(clientSocket, buffer, sizeof(buffer), 0);
        if (bytesReceived > 0) {
            buffer[bytesReceived] = '\0'; // Null-terminate the received message
            std::string message(buffer);
            std::cout << "Server received: " << message << std::endl;

            // Broadcast the message to all other clients
            BroadcastMessage(message, clientSocket);
        } else if (bytesReceived == 0) {
            std::cout << "Client disconnected." << std::endl;
            break; // Client disconnected gracefully
        } else {
            std::cerr << "Error in receiving data: " << WSAGetLastError() << std::endl;
            break; // Error occurred
        }
    }

    // Clean up client socket
    closesocket(clientSocket);
    clients.erase(std::remove(clients.begin(), clients.end(), clientSocket), clients.end());
}

int main() {
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        std::cerr << "WSAStartup failed." << std::endl;
        return -1;
    }

    SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSocket == INVALID_SOCKET) {
        std::cerr << "Failed to create server socket: " << WSAGetLastError() << std::endl;
        WSACleanup();
        return -1;
    }

    sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(54000);
    serverAddr.sin_addr.s_addr = INADDR_ANY;

    if (bind(serverSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
        std::cerr << "Binding failed: " << WSAGetLastError() << std::endl;
        closesocket(serverSocket);
        WSACleanup();
        return -1;
    }

    if (listen(serverSocket, SOMAXCONN) == SOCKET_ERROR) {
        std::cerr << "Listening failed: " << WSAGetLastError() << std::endl;
        closesocket(serverSocket);
        WSACleanup();
        return -1;
    }

    std::cout << "Server is listening on port 54000" << std::endl;

    while (true) {
        sockaddr_in clientAddr;
        int clientSize = sizeof(clientAddr);
        SOCKET clientSocket = accept(serverSocket, (sockaddr*)&clientAddr, &clientSize);

        if (clientSocket != INVALID_SOCKET) {
            clients.push_back(clientSocket); // Add client to the list
            std::cout << "New client connected!" << std::endl;

            std::thread(ClientHandler, clientSocket).detach(); // Start a new thread for this client
        } else {
            std::cerr << "Invalid client socket: " << WSAGetLastError() << std::endl;
        }
    }

    closesocket(serverSocket);
    WSACleanup();
    return 0;
}
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS

#include <winsock2.h>
#include <windows.h>
#include <commctrl.h>
#include <thread>
#include <string>
#include <mutex>

#pragma comment(lib, "ws2_32.lib")

// Function prototypes
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void ReceiveMessages(SOCKET sock);
void UpdateChatWindow(const std::string& message);

// Global variables
HWND hChatArea;
HWND hInputField;
SOCKET clientSocket;
std::mutex chatMutex;

int main() {
    // Initialize Winsock
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    // Create a socket
    clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (clientSocket == INVALID_SOCKET) {
        MessageBox(NULL, "Failed to create socket.", "Error", MB_OK | MB_ICONERROR);
        return -1;
    }

    sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(54000);
    serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    // Connect to server
    if (connect(clientSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
        MessageBox(NULL, "Failed to connect to server.", "Error", MB_OK | MB_ICONERROR);
        closesocket(clientSocket);
        return -1;
    }

    // Create main window
    const char CLASS_NAME[] = "ChatClient";
    WNDCLASS wc = { };
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = GetModuleHandle(NULL);
    wc.lpszClassName = CLASS_NAME;

    RegisterClass(&wc);

    HWND hwnd = CreateWindowEx(
        0,
        CLASS_NAME,
        "Chat Client",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 400, 300,
        NULL,
        NULL,
        GetModuleHandle(NULL),
        NULL
    );

    ShowWindow(hwnd, SW_SHOW);
    UpdateWindow(hwnd);

    // Start a thread to handle incoming messages
    std::thread receiveThread(ReceiveMessages, clientSocket);
    receiveThread.detach();

    // Message loop
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    closesocket(clientSocket);
    WSACleanup();
    return 0;
}

// Window Procedure
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    static HINSTANCE hInst = GetModuleHandle(NULL);
    switch (uMsg) {
    case WM_CREATE: {
        // Create chat area
        hChatArea = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
            WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_READONLY,
            10, 10, 360, 200, hwnd, NULL, hInst, NULL);

        // Create input field
        hInputField = CreateWindowEx(0, "EDIT", "",
            WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
            10, 220, 280, 25, hwnd, NULL, hInst, NULL);

        // Create send button
        CreateWindow("BUTTON", "Send",
            WS_CHILD | WS_VISIBLE,
            300, 220, 70, 25, hwnd, (HMENU)1, hInst, NULL);
    } break;

    case WM_COMMAND:
        if (LOWORD(wParam) == 1) { // Send button clicked
            char buffer[1024];
            GetWindowText(hInputField, buffer, sizeof(buffer));

            if (strlen(buffer) > 0) {
                send(clientSocket, buffer, strlen(buffer), 0);
                UpdateChatWindow("You: " + std::string(buffer));
                SetWindowText(hInputField, ""); // Clear input field
            }
        }
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

// Function to receive messages from the server
void ReceiveMessages(SOCKET sock) {
    char buffer[1024];
    while (true) {
        ZeroMemory(buffer, sizeof(buffer));
        int bytesReceived = recv(sock, buffer, sizeof(buffer), 0);

        if (bytesReceived > 0) {
            buffer[bytesReceived] = '\0'; // Null-terminate the received message
            UpdateChatWindow("Server: " + std::string(buffer));
        } else if (bytesReceived == 0) {
            UpdateChatWindow("Server closed the connection.");
            break;
        } else {
            UpdateChatWindow("Error receiving data.");
            break;
        }
    }
}

// Function to update the chat area
void UpdateChatWindow(const std::string& message) {
    chatMutex.lock();
    SendMessage(hChatArea, EM_SETSEL, -1, -1); // Move cursor to end
    SendMessage(hChatArea, EM_REPLACESEL, TRUE, (LPARAM)message.c_str());
    SendMessage(hChatArea, EM_REPLACESEL, TRUE, (LPARAM)"\r\n");
    chatMutex.unlock();
} make this code and app better without changing much