/*  
	EQ2Emulator:  Everquest II Server Emulator
	Copyright (C) 2007  EQ2EMulator Development Team (http://www.eq2emulator.net)

	This file is part of EQ2Emulator.
*/

#pragma once

// Linux network headers
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

// Standard library includes
#include <atomic>
#include <cstdint>
#include <string>
#include <string_view>
#include <memory>

// Project includes
#include "../common/types.h"
#include "../common/Web/WebServer.h"
#include "../common/MiscFunctions.h"

// Forward declarations
class LWorld;

/**
 * @brief Signal handler for graceful shutdown
 * @param sig_num Signal number received
 */
void CatchSignal(int sig_num);

/**
 * @brief Server operation modes
 */
enum class ServerMode : std::uint8_t 
{
    Standalone, // Server operates independently
    Master,     // Server acts as master node
    Slave,      // Server acts as slave node
    Mesh        // Server participates in mesh network
};

/**
 * @brief Main network connection manager for the login server
 * 
 * This class handles all network operations for the login server including:
 * - Client connections and authentication
 * - World server connections
 * - Configuration management
 * - Web server integration
 */
class NetConnection
{
public:
    /**
     * @brief Default constructor - initializes all network settings to defaults
     */
    NetConnection() noexcept;
    
    /**
     * @brief Destructor - ensures proper cleanup of network resources
     */
    ~NetConnection();
    
    // Disable copy operations (network connection should be unique)
    NetConnection(const NetConnection&) = delete;
    NetConnection& operator=(const NetConnection&) = delete;
    
    // Enable move operations for potential future use
    NetConnection(NetConnection&&) = default;
    NetConnection& operator=(NetConnection&&) = default;
    
    /**
     * @brief Updates the console window title with server statistics
     * @param new_title Optional custom title (nullptr uses default format)
     * Note: This is a no-op on Linux but kept for API compatibility
     */
    void UpdateWindowTitle(const char* new_title = nullptr);
    
    /**
     * @brief Initializes the network connection
     * @return true if initialization successful, false otherwise
     */
    bool Init();
    
    /**
     * @brief Listens for new client connections
     */
    void ListenNewClients();
    
    /**
     * @brief Reads configuration from the login config file
     * @return true if config loaded successfully, false otherwise
     */
    bool ReadLoginConfig();
    
    /**
     * @brief Displays the welcome header with version and copyright info
     */
    void WelcomeHeader();
    
    /**
     * @brief Initializes the web server for HTTP/HTTPS API access
     * @param web_ipaddr IP address to bind the web server to
     * @param web_port Port number for the web server
     * @param cert_file Path to SSL certificate file
     * @param key_file Path to SSL key file
     * @param key_password Password for the SSL key
     * @param hardcode_user Hardcoded username for basic auth
     * @param hardcode_password Hardcoded password for basic auth
     */
    void InitWebServer(std::string_view web_ipaddr, 
                      std::uint16_t web_port,
                      std::string_view cert_file,
                      std::string_view key_file,
                      std::string_view key_password,
                      std::string_view hardcode_user,
                      std::string_view hardcode_password);
    
    // Static web server request handlers
    /**
     * @brief Handles /status endpoint requests
     * @param req HTTP request object
     * @param res HTTP response object to populate
     */
    static void Web_loginhandle_status(const http::request<http::string_body>& req, 
                                       http::response<http::string_body>& res);
    
    /**
     * @brief Handles /worlds endpoint requests
     * @param req HTTP request object
     * @param res HTTP response object to populate
     */
    static void Web_loginhandle_worlds(const http::request<http::string_body>& req,
                                       http::response<http::string_body>& res);
    
    // Getter methods for configuration values
    [[nodiscard]] std::uint16_t GetPort() const noexcept { return port_; }
    [[nodiscard]] ServerMode GetLoginMode() const noexcept { return login_mode_; }
    [[nodiscard]] const char* GetMasterAddress() const noexcept { return master_address_.data(); }
    [[nodiscard]] std::uint16_t GetUplinkPort() const noexcept 
    { 
        return (uplink_port_ != 0) ? uplink_port_ : port_; 
    }
    [[nodiscard]] const char* GetUplinkAccount() const noexcept { return uplink_account_.data(); }
    [[nodiscard]] const char* GetUplinkPassword() const noexcept { return uplink_password_.data(); }
    [[nodiscard]] bool IsAllowingAccountCreation() const noexcept { return allow_account_creation_; }
    [[nodiscard]] std::uint32_t GetExpansionFlag() const noexcept { return expansion_flag_; }
    [[nodiscard]] std::uint8_t GetCitiesFlag() const noexcept { return cities_flag_; }
    [[nodiscard]] std::uint32_t GetDefaultSubscriptionLevel() const noexcept { return default_subscription_level_; }
    [[nodiscard]] std::uint32_t GetEnabledRaces() const noexcept { return enabled_races_; }
    [[nodiscard]] const std::string& GetWebLoginAddress() const noexcept { return web_login_address_; }
    [[nodiscard]] std::uint16_t GetWebLoginPort() const noexcept { return web_login_port_; }
    [[nodiscard]] const std::string& GetWebCertFile() const noexcept { return web_cert_file_; }
    [[nodiscard]] const std::string& GetWebKeyFile() const noexcept { return web_key_file_; }
    [[nodiscard]] const std::string& GetWebKeyPassword() const noexcept { return web_key_password_; }
    [[nodiscard]] const std::string& GetWebHardcodeUser() const noexcept { return web_hardcode_user_; }
    [[nodiscard]] const std::string& GetWebHardcodePassword() const noexcept { return web_hardcode_password_; }
    
    // Setter methods for configuration values
    void SetPort(std::uint16_t port) noexcept { port_ = port; }
    
    // Public state variables
    char address[1024]{};                        // Server address buffer
    std::atomic<std::int32_t> numclients{0};    // Current number of connected clients
    std::atomic<std::int32_t> numservers{0};    // Current number of connected world servers
    std::atomic<bool> login_running{false};      // Flag indicating if login server is running
    std::atomic<std::int64_t> login_uptime{0};   // Timestamp when server started
    
protected:
    friend class LWorld;  // Allow LWorld access to protected members
    
    /**
     * @brief Flag indicating uplink version mismatch
     */
    bool uplink_wrong_version_{false};
    
private:
    // Network configuration
    std::uint16_t port_{5999};                           // Server listening port
    int listening_socket_{0};                            // Main listening socket descriptor
    
    // Master server configuration (for non-standalone modes)
    std::array<char, 300> master_address_{};             // Master server address
    std::uint16_t uplink_port_{0};                       // Port for uplink connection
    std::array<char, 300> uplink_account_{};             // Account for uplink authentication
    std::array<char, 300> uplink_password_{};            // Password for uplink authentication
    ServerMode login_mode_{ServerMode::Standalone};      // Current server operation mode
    
    // Account and expansion settings
    bool allow_account_creation_{true};                  // Allow new account creation
    std::uint32_t expansion_flag_{0x7CFF};              // Enabled expansions bitfield
    std::uint8_t cities_flag_{0xFF};                    // Enabled starting cities bitfield
    std::uint32_t default_subscription_level_{0xFFFFFFFF}; // Default subscription level for new accounts
    std::uint32_t enabled_races_{0xFFFF};               // Enabled races bitfield
    
    // Web server configuration
    std::string web_login_address_;                      // Web server bind address
    std::string web_cert_file_;                          // SSL certificate file path
    std::string web_key_file_;                           // SSL key file path
    std::string web_key_password_;                       // SSL key password
    std::string web_hardcode_user_;                      // Basic auth username
    std::string web_hardcode_password_;                  // Basic auth password
    std::uint16_t web_login_port_{0};                   // Web server port
    std::unique_ptr<WebServer> login_webserver_;         // Web server instance
};