/*
 * Copyright © Canonical Ltd.
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 or 3,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef MIR_SERVER_CONFIGURATION_H_
#define MIR_SERVER_CONFIGURATION_H_

#include <functional>
#include <memory>
#include <vector>

struct wl_display;

namespace mir
{
namespace cookie
{
class Authority;
}
namespace compositor
{
class Compositor;
class ScreenShooter;
class ScreenShooterFactory;
}
namespace frontend
{
class Connector;
}
namespace shell
{
class SessionContainer;
class Shell;
class IdleHandler;
class TokenAuthority;
}
namespace graphics
{
class Display;
class DisplayConfigurationPolicy;
class DisplayPlatform;
class RenderingPlatform;
}
namespace input
{
class InputManager;
class InputDispatcher;
class EventFilter;
}

namespace scene
{
class ApplicationNotRespondingDetector;
class Session;
class Clipboard;
class TextInputHub;
class IdleHub;
class SessionLock;
}

class MainLoop;
class ServerStatusListener;
class DisplayChanger;
class EmergencyCleanup;
class ConsoleServices;
class DecorationStrategy;

class ServerConfiguration
{
public:
    // TODO most of these interfaces are wider DisplayServer needs...
    // TODO ...some or all of them need narrowing
    virtual std::shared_ptr<frontend::Connector> the_wayland_connector() = 0;
    virtual std::shared_ptr<frontend::Connector> the_xwayland_connector() = 0;
    virtual std::shared_ptr<graphics::Display> the_display() = 0;
    virtual std::shared_ptr<compositor::Compositor> the_compositor() = 0;
    virtual std::shared_ptr<compositor::ScreenShooterFactory> the_screen_shooter_factory() = 0;
    virtual std::shared_ptr<input::InputManager> the_input_manager() = 0;
    virtual std::shared_ptr<input::InputDispatcher> the_input_dispatcher() = 0;
    virtual std::shared_ptr<MainLoop> the_main_loop() = 0;
    virtual std::shared_ptr<ServerStatusListener> the_server_status_listener() = 0;
    virtual std::shared_ptr<DisplayChanger> the_display_changer() = 0;
    virtual auto the_console_services() -> std::shared_ptr<ConsoleServices> = 0;
    virtual auto the_display_platforms() -> std::vector<std::shared_ptr<graphics::DisplayPlatform>> const& = 0;
    virtual auto the_rendering_platforms() -> std::vector<std::shared_ptr<graphics::RenderingPlatform>> const& = 0;
    virtual std::shared_ptr<EmergencyCleanup> the_emergency_cleanup() = 0;
    virtual std::shared_ptr<scene::Clipboard> the_main_clipboard() = 0;
    virtual std::shared_ptr<scene::Clipboard> the_primary_selection_clipboard() = 0;
    virtual std::shared_ptr<scene::TextInputHub> the_text_input_hub() = 0;
    virtual std::shared_ptr<scene::IdleHub> the_idle_hub() = 0;
    virtual std::shared_ptr<shell::IdleHandler> the_idle_handler() = 0;
    virtual std::shared_ptr<shell::TokenAuthority> the_token_authority() = 0;
    virtual std::function<void()> the_stop_callback() = 0;
    virtual void add_wayland_extension(
        std::string const& name,
        std::function<std::shared_ptr<void>(
            wl_display*,
            std::function<void(std::function<void()>&& work)> const&)> builder) = 0;
    virtual std::shared_ptr<scene::SessionLock> the_session_lock() = 0;

    using WaylandProtocolExtensionFilter = std::function<bool(std::shared_ptr<scene::Session> const&, char const*)>;

    /// Set a policy for the provided wayland extension.
    ///
    /// Only clients whose \p policy returns `true` will be allowed to use the interface
    /// given by \p interface_name.
    ///
    /// \param interface_name the interface to apply the policy on
    /// \param policy the policy predicate with the session and interface name provided
    ///               as arguments.
    virtual void set_wayland_extension_policy(
        std::string const& interface_name,
        std::function<bool(std::shared_ptr<scene::Session> const&, const char*)> const& policy) = 0;

    virtual auto the_decoration_strategy() -> std::shared_ptr<DecorationStrategy> = 0;
    virtual void set_the_decoration_strategy(std::shared_ptr<DecorationStrategy> strategy) = 0;
protected:
    ServerConfiguration() = default;
    virtual ~ServerConfiguration() = default;

    ServerConfiguration(ServerConfiguration const&) = delete;
    ServerConfiguration& operator=(ServerConfiguration const&) = delete;
};
}


#endif /* MIR_SERVER_CONFIGURATION_H_ */
