// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-

const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Main = imports.ui.main;

const ScreenSaverIface =
    '<node> \
        <interface name="org.cinnamon.ScreenSaver"> \
        <method name="GetActive"> \
            <arg type="b" direction="out" /> \
        </method> \
        <method name="GetActiveTime"> \
            <arg type="u" direction="out" /> \
        </method> \
        <method name="Lock"> \
            <arg type="s" direction="in" /> \
        </method> \
        <method name="SetActive"> \
            <arg type="b" direction="in" /> \
        </method> \
        <method name="Quit" /> \
        <method name="SimulateUserActivity" /> \
        <signal name="ActiveChanged"> \
            <arg type="b" direction="out" /> \
        </signal> \
        </interface> \
    </node>';

const ScreenSaverInfo = Gio.DBusInterfaceInfo.new_for_xml(ScreenSaverIface);

/**
 * ScreenSaverService:
 *
 * Implements the org.cinnamon.ScreenSaver DBus interface.
 * Routes calls to the internal screensaver (this._screenShield).
 *
 * Note: If internal-screensaver-enabled is false, Cinnamon must be restarted
 * to allow the external cinnamon-screensaver daemon to claim the bus name.
 */
var ScreenSaverService = class ScreenSaverService {
    constructor(screenShield) {
        this._screenShield = screenShield;

        this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ScreenSaverIface, this);
        this._dbusImpl.export(Gio.DBus.session, '/org/cinnamon/ScreenSaver');

        Gio.DBus.session.own_name('org.cinnamon.ScreenSaver',
                                   Gio.BusNameOwnerFlags.REPLACE,
                                   null, null);

        if (this._screenShield) {
            this._screenShield.connect('locked', this._onLocked.bind(this));
            this._screenShield.connect('unlocked', this._onUnlocked.bind(this));
        }
    }

    _onLocked() {
        this._emitActiveChanged(true);
    }

    _onUnlocked() {
        this._emitActiveChanged(false);
    }

    _emitActiveChanged(isActive) {
        if (this._dbusImpl) {
            this._dbusImpl.emit_signal('ActiveChanged',
                                        GLib.Variant.new('(b)', [isActive]));
        }
    }

    GetActiveAsync(params, invocation) {
        let isActive = this._screenShield.isLocked();
        invocation.return_value(GLib.Variant.new('(b)', [isActive]));
    }

    GetActiveTimeAsync(params, invocation) {
        let activeTime = this._screenShield.getActiveTime();
        invocation.return_value(GLib.Variant.new('(u)', [activeTime]));
    }

    LockAsync(params, invocation) {
        let [message] = params;

        if (!Main.lockdownSettings.get_boolean('disable-lock-screen')) {
            this._screenShield.lock(true, message || null);
        }

        invocation.return_value(null);
    }

    QuitAsync(params, invocation) {
        // No-op for internal screensaver (can't quit Cinnamon's built-in screen shield).
        // Exists for compatibility with legacy cinnamon-screensaver-command --exit.
        invocation.return_value(null);
    }

    SimulateUserActivityAsync(params, invocation) {
        this._screenShield.simulateUserActivity();
        invocation.return_value(null);
    }

    SetActiveAsync(params, invocation) {
        let [active] = params;

        if (this._screenShield) {
            if (active) {
                this._screenShield.activate();
            } else {
                // Can't deactivate if locked
                if (!this._screenShield.isLocked()) {
                    this._screenShield.deactivate();
                }
            }
        }

        invocation.return_value(null);
    }
};

/**
 * Creates a proxy to the DBus service (which may be internal or external).
 * (Deprecated as of 6.8)
 * Extensions should connect to Main.screensaverController. Continuing to
 * use this is still reliable, but is not as immediately up-to-date when the
 * internal screensaver is in use.
 */
function ScreenSaverProxy() {
    var self = new Gio.DBusProxy({
        g_connection: Gio.DBus.session,
        g_interface_name: ScreenSaverInfo.name,
        g_interface_info: ScreenSaverInfo,
        g_name: 'org.cinnamon.ScreenSaver',
        g_object_path: '/org/cinnamon/ScreenSaver',
        g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START |
                 Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES)
    });
    self.init(null);

    return self;
}