/**
 * Copyright (c) 2025
 *    Marcus Britanicus (https://gitlab.com/marcusbritanicus)
 *
 * DFL::IPC::Wayfire is the class to handle communication between Wayfire
 * and a client.
 **/

#pragma once

#include <QtCore>

namespace DFL {
    namespace IPC {
        class Wayfire;
        class WayfireImpl;
    }
}

class DFL::IPC::Wayfire : public QObject {
    Q_OBJECT

    public:
        Wayfire( QString wfSock = QString() );
        ~Wayfire();

        /** Connect to Wayfire */
        bool connectToServer();

        /* ========== Specific requests ========== */

        /** Request the compositor to send us the outputs information */
        QJsonArray listOutputs();

        /** Request the compositor to focus a given output */
        bool focusOutput( int64_t );

        /** Request the compositor to trigger show-desktop a given output */
        bool showDesktop( int64_t );

        /** Request the compositor to send us the wsets information */
        QJsonDocument getWorkspaceSetsInfo();

        /** Request the compositor to change the current workspace */
        bool switchToWorkspace( int64_t output, int64_t row, int64_t column );

        /** Request the compositor to send us the list of views */
        QJsonArray listViews();

        /** Request the compositor to send us the info of the given view */
        QJsonObject getViewInfo( int64_t id );

        /** Request the compositor to focus a given view */
        bool focusView( int64_t );

        /** Request the compositor to minimize/restore a given view */
        bool minimizeView( int64_t, bool );

        /** Request the compositor to maximize/restore a given view */
        bool maximizeView( int64_t, bool );

        /** Request the compositor to fullscreen a given view */
        bool fullscreenView( int64_t, bool );

        /** Request the compositor to focus a given view */
        bool restoreView( int64_t );

        /** Request the compositor to focus a given view */
        bool closeView( int64_t );

        /** This is a generic request */
        QJsonDocument genericRequest( QJsonDocument );

        /* ========== WAYFIRE EVENTS ========== */

        /**
         * A new output was added.
         */
        Q_SIGNAL void outputAdded( QJsonDocument );

        /**
         * An existing output was removed.
         */
        Q_SIGNAL void outputRemoved( QJsonDocument );

        /**
         * A particular output has gained focus.
         * Only one output can have focus at any given time.
         * This outupt can be used to calculate the focused view.
         */
        Q_SIGNAL void outputFocused( QJsonDocument );

        /**
         * Current workspace set of a given output was changed
         * When the wset of an output changes, always query the workspace
         */
        Q_SIGNAL void workspaceSetChanged( QJsonDocument );

        /**
         * The active workspace of a given wset changed.
         * Because wsets of different outputs are independent,
         * workspace change on one output will not affect the other.
         */
        Q_SIGNAL void workspaceChanged( QJsonDocument );

        /**
         * A view was just mapped.
         * This view does not have an output nor a wset.
         * Even the title and app-id will be unset.
         * Only the view id is valid.
         */
        Q_SIGNAL void viewMapped( QJsonDocument );

        /**
         * A view on a particular outupt gained focus
         * Since wayfire supports independent outputs, each output can
         * have a view with focus. The focused view of the active outupt
         * will be the one with keyboard focus.
         */
        Q_SIGNAL void viewFocused( QJsonDocument );

        /**
         * The title of a view changed. The title can be "nil" or null.
         * In such cases, the user can safely ignore it.
         */
        Q_SIGNAL void viewTitleChanged( QJsonDocument );

        /**
         * The app-id of a view changed. The app-id can be "nil" or null.
         * In such cases, the user can safely ignore it.
         */
        Q_SIGNAL void viewAppIdChanged( QJsonDocument );

        /**
         * The geometry of a view changed.
         */
        Q_SIGNAL void viewGeometryChanged( QJsonDocument );

        /**
         * The tiled status of a view has changed.
         */
        Q_SIGNAL void viewTiled( QJsonDocument );

        /**
         * A view was minimized.
         */
        Q_SIGNAL void viewMinimized( QJsonDocument );

        /**
         * The output of a view changed. When the view gets mapped, the
         * output will be null.
         */
        Q_SIGNAL void viewOutputChanged( QJsonDocument );

        /**
         * The workspace of a view changed.
         */
        Q_SIGNAL void viewWorkspaceChanged( QJsonDocument );

        /**
         * An existing view was unmapped.
         * The output, wset etc of this view are invalid as of now.
         */
        Q_SIGNAL void viewUnmapped( QJsonDocument );

        /**
         * A generic wayfire event.
         * This signal is always emitted for all events.
         * Specific signals are emitted by parsing this event.
         */
        Q_SIGNAL void genericEvent( QJsonDocument );

        /**
         * Inform the user tha there was an error
         * Currently used to indicate failure in watching for wayfire events.
         */
        Q_SIGNAL void error();

    private:
        /** Implementation class pointer */
        WayfireImpl *impl = nullptr;

        /** Partially parse the events to emit the correct signals */
        void parseEvents( QJsonDocument );
};
