//
//  HTTPDaemon.h
//

#pragma once

#include <windows.h>
#include <process.h>
#include <stdlib.h>
#include <winsock.h>

#include "Raym/Raym.h"

#include "net/HTTPRequest.h"
#include "net/HTTPResponse.h"


namespace NET
{

class HTTPDaemonDelegate
{
public:
    virtual HTTPRequest *readRequest(SOCKET sock) = 0;
    virtual HTTPResponse *request(HTTPRequest *request, SOCKET sock, struct sockaddr_in *client) = 0;

};

class HTTPDaemon : public Raym::Object
{
private:
    int                     _port;
    int                     _backlog;
    HTTPDaemonDelegate *    _delegate;
    Raym::String *          _rootPath;
    enum _state
    {
        ST_IDLE,
        ST_READY,
        ST_RUN,
        ST_DONE
    }                       _state;

protected:
    HTTPDaemon();
    ~HTTPDaemon();

public:
    static HTTPDaemon *alloc();
    HTTPDaemon *initWithPort(int port, int backlog);

    void setDelegate(HTTPDaemonDelegate *delegate);
    void setRootPath(Raym::String *path);
    Raym::String *rootPath();
    void run();
    bool start();
    void stop();
    void wait();

    HTTPResponse *responseWithReason(Raym::String *reason, int status, Raym::String *version);
    HTTPResponse *responseWithPath(Raym::String *path, HTTPRequest *request);
    static HTTPResponse *responseOfUnnecessary();
    static Raym::String *reasonForStatus(int status);

    // for internal use
    Raym::Array * _sockets;
    void session(SOCKET sock, struct sockaddr_in *client);

    virtual const char *className();
};


class HTTPDaemonSessionArgs
{
public:
    HTTPDaemon *        _daemon;
    SOCKET              _sock;
    struct sockaddr_in  _client;
};

} // NET
