/**
 * Copyright (c) 2022
 *    Marcus Britanicus (https://gitlab.com/marcusbritanicus)
 *    Abrar (https://gitlab.com/s96abrar)
 *
 * This code is inspired from
 * https://github.com/monicaphalswal/unix-domain-socket-chat-client-server
 *
 * DFL::IPC::Server is unix domain socket based server, wrapped in Qt/C++
 * class for convenience of use. This class is used in conjunction with
 * DFL::IPC:Client to communicate between two instances of the same app.
 **/

#pragma once

/** For struct pollfd */
#include <poll.h>

/* For QString, QThread, QTimer, etc.. */
#include <QtCore>

namespace DFL {
    namespace IPC {
        class Server;
        class ServerImpl;
    }
}

class DFL::IPC::Server : public QObject {
    Q_OBJECT;

    public:

        /**
         * @path is the socket path.
         */
        Server( QString path, QObject *parent = nullptr );
        ~Server();

        /**
         * Start the server.
         * Returns true on success, else false.
         * Suitable signals are also emitted.
         */
        bool startServer();

        /**
         * Broadcast a message to all listeners
         * This is similar to emit signal( ... )
         */
        void broadcast( QString );

        /**
         * Reply to an incoming message.
         * @fd is the client's fd.
         */
        bool reply( int fd, QString msg );

        /**
         * Shutdown the server.
         * All clients will be automatically disconnected.
         */
        void shutdown();

    private:

        /**
         * Handle an incoming connection
         * This will have a unique fd, which will be watched for messages.
         */
        int incomingConnection( int clientFD );

        /**
         * Create unique ID;
         */
        QString createUniqueID();

        /** Socket path */
        QString mSockPath;

        /** Our main work-horse */
        DFL::IPC::ServerImpl *impl;

    Q_SIGNALS:
        /* Relay the commands */
        void messageReceived( QString, int );

        /** General socket error */
        void socketError( int );

        /** Disconencted from the server */
        void disconnected();
};
