#pragma once
#include <csignal>
#include <memory>
#include <gtkmm/cssprovider.h>
#include <gtk4-session-lock.h>
#include <wayland-client.h>

#include "glibmm/refptr.h"
#include "lockscreen.hpp"
#include "sigc++/connection.h"
#include "wf-shell-app.hpp"
#include "plugin.hpp"

using Plugin = std::shared_ptr<WayfireLockerPlugin>;
void on_session_locked_c(GtkSessionLockInstance *lock, void *data);
void on_session_lock_failed_c(GtkSessionLockInstance *lock, void *data);
void on_session_unlocked_c(GtkSessionLockInstance *lock, void *data);
void on_monitor_present_c(GtkSessionLockInstance *lock, GdkMonitor *monitor, void *data);

enum ExitType
{
    USER_UNLOCKED    = SIGUSR1,
    LOCKED           = SIGHUP,
    ERROR_NOT_LOCKED = SIGTERM,
};

class WayfireLockerApp : public WayfireShellApp
{
  private:
    WayfireLockerApp(WayfireLockerApp const& copy);
    WayfireLockerApp& operator =(WayfireLockerApp const& copy);

    std::string get_config_file() override;

    GtkSessionLockInstance *lock;
    std::map<std::string, Plugin> plugins = {};

    bool m_is_debug    = false;
    bool m_is_locked   = false;
    bool instant_lock  = false;
    int bad_auth_count = 0;
    bool lockout = false;
    std::string cache_file = "";
    std::string background_path = "";
    pid_t p_pid;

    int inotify_bg_file;
    Glib::RefPtr<BackgroundImage> background_file;


    std::vector<Glib::RefPtr<Gtk::CssProvider>> css_rules;
    sigc::connection lockout_signal, prewake_signal;
    std::vector<sigc::connection> windows_signals;

  public:
    using WayfireShellApp::WayfireShellApp;
    static void create(pid_t p_pid, bool now);
    static WayfireLockerApp& get()
    {
        return (WayfireLockerApp&)WayfireShellApp::get();
    }

    Gio::Application::Flags get_extra_application_flags() override;
    std::string get_application_name() override;

    /* Starts the program. get() is valid afterward the first (and the only)
     * call to create() */
    void on_monitor_present(GdkMonitor *monitor);
    void on_activate() override;
    bool is_debug()
    {
        return m_is_debug;
    }

    bool exit_on_unlock = true;


    bool is_locked();
    void set_is_locked(bool locked);
    WayfireLockerApp(bool now);
    ~WayfireLockerApp();

    Plugin get_plugin(std::string name);

    /* Give commands to compositor about lock state, or emulate them*/
    void perform_unlock(std::string reason);
    void perform_lock();
    void init_plugins();
    void deinit_plugins();
    bool can_early_wake = true;
    void user_activity();

    void recieved_bad_auth();
    bool is_locked_out();
    void reload_background();

    /* Send a signal to parent process
     *  SIGHUP = We are successfully locked. exit(0)
     *  SIGTERM = An error occured, and we did not lock. exit(2)
     */
    void kill_parent(ExitType);

    std::map<std::string, std::shared_ptr<WayfireLockerAppLockscreen>> window_list;
};
