#pragma once

#include "types.h"
#include <vector>
#include <string>
#include <memory>
#include <cstring>

namespace scar {

// Wire format message header
struct MessageHeader {
    uint32_t length;        // Total message length including header
    MessageType type;       // Message type
    uint8_t version;        // Protocol version
    uint16_t reserved;      // Reserved for future use
} __attribute__((packed));

class Message {
public:
    Message(MessageType type);
    virtual ~Message() = default;
    
    MessageType type() const { return header_.type; }
    
    // Serialize to wire format
    virtual std::vector<uint8_t> serialize() const;
    
    // Deserialize from wire format
    static std::unique_ptr<Message> deserialize(const std::vector<uint8_t>& data);
    
protected:
    MessageHeader header_;
    std::vector<uint8_t> payload_;
    
    void setPayload(const std::vector<uint8_t>& data);
    const std::vector<uint8_t>& payload() const { return payload_; }
};

// Login request message
class LoginRequest : public Message {
public:
    LoginRequest(const std::string& username, const std::string& password);
    
    std::vector<uint8_t> serialize() const override;
    
    static std::unique_ptr<LoginRequest> deserialize(const std::vector<uint8_t>& payload);
    
    const std::string& username() const { return username_; }
    const std::string& password() const { return password_; }
    
private:
    std::string username_;
    std::string password_;
};

// Login response message
class LoginResponse : public Message {
public:
    LoginResponse(bool success, const std::string& token = "", ErrorCode error = ErrorCode::NONE);
    
    std::vector<uint8_t> serialize() const override;
    
    static std::unique_ptr<LoginResponse> deserialize(const std::vector<uint8_t>& payload);
    
    bool success() const { return success_; }
    const std::string& token() const { return token_; }
    ErrorCode error() const { return error_; }
    
private:
    bool success_;
    std::string token_;
    ErrorCode error_;
};

// Text message
class TextMessage : public Message {
public:
    TextMessage(const std::string& sender, const std::string& content);
    
    std::vector<uint8_t> serialize() const override;
    
    static std::unique_ptr<TextMessage> deserialize(const std::vector<uint8_t>& payload);
    
    const std::string& sender() const { return sender_; }
    const std::string& content() const { return content_; }
    
private:
    std::string sender_;
    std::string content_;
};

// Screen share start message
class ScreenShareStart : public Message {
public:
    ScreenShareStart(uint32_t width, uint32_t height);
    
    std::vector<uint8_t> serialize() const override;
    
    static std::unique_ptr<ScreenShareStart> deserialize(const std::vector<uint8_t>& payload);
    
    uint32_t width() const { return width_; }
    uint32_t height() const { return height_; }
    
private:
    uint32_t width_;
    uint32_t height_;
};

// Screen share data message
class ScreenShareData : public Message {
public:
    ScreenShareData(const std::vector<uint8_t>& frameData);
    
    std::vector<uint8_t> serialize() const override;
    
    static std::unique_ptr<ScreenShareData> deserialize(const std::vector<uint8_t>& payload);
    
    const std::vector<uint8_t>& frameData() const { return frameData_; }
    
private:
    std::vector<uint8_t> frameData_;
};

// Screen share stop message
class ScreenShareStop : public Message {
public:
    ScreenShareStop();
    
    std::vector<uint8_t> serialize() const override;
    
    static std::unique_ptr<ScreenShareStop> deserialize(const std::vector<uint8_t>& payload);
};

} // namespace scar
