/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */

const Interfaces = imports.misc.interfaces;
const Gdk = imports.gi.Gdk;
const GLib = imports.gi.GLib;
const CinnamonDesktop = imports.gi.CinnamonDesktop;
const Lang = imports.lang;
const Applet = imports.ui.applet;
const PopupMenu = imports.ui.popupMenu;

const N_ = function(e) { return e; };

const possibleRotations = [
    CinnamonDesktop.RRRotation.ROTATION_0,
    CinnamonDesktop.RRRotation.ROTATION_90,
    CinnamonDesktop.RRRotation.ROTATION_180,
    CinnamonDesktop.RRRotation.ROTATION_270
];

let rotations = [
    [CinnamonDesktop.RRRotation.ROTATION_0, N_("Normal")],
    [CinnamonDesktop.RRRotation.ROTATION_90, N_("Left")],
    [CinnamonDesktop.RRRotation.ROTATION_270, N_("Right")],
    [CinnamonDesktop.RRRotation.ROTATION_180, N_("Upside-down")]
];

class CinnamonXrandrApplet extends Applet.IconApplet {
    constructor(orientation, panel_height, instance_id) {
        super(orientation, panel_height, instance_id);

        this.set_applet_icon_symbolic_name("preferences-desktop-display");
        this.set_applet_tooltip(_("Display"));

        this.menuManager = new PopupMenu.PopupMenuManager(this);
        this.menu = new Applet.AppletPopupMenu(this, orientation);
        this.menuManager.addMenu(this.menu);

        Interfaces.getDBusProxyAsync("org.cinnamon.SettingsDaemon.XRANDR_2", Lang.bind(this, function(proxy, error) {
            this._proxy = proxy;
        }));

        try {
            this._screen = new CinnamonDesktop.RRScreen({ gdk_screen: Gdk.Screen.get_default() });
            this._screen.init(null);
        } catch(e) {
            // an error means there is no XRandR extension
            global.logError(e);
            this.actor.hide();
            return;
        }

        this._createMenu();
        this._screen.connect('changed', Lang.bind(this, this._randrEvent));
    }

    on_applet_clicked(event) {
        this.menu.toggle();
    }

    _randrEvent() {
        this.menu.removeAll();
        this._createMenu();
    }

    _createMenu() {
        let config = CinnamonDesktop.RRConfig.new_current(this._screen);
        let outputs = config.get_outputs();
        for (let i = 0; i < outputs.length; i++) {
            if (outputs[i].is_connected())
                this._addOutputItem(config, outputs[i]);
        }
        this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
        this.menu.addAction(_("Configure display settings..."), function() {
            GLib.spawn_command_line_async('cinnamon-settings display');
        });
    }

    _addOutputItem(config, output) {
        let item = new PopupMenu.PopupMenuItem("%s (%s)".format(output.get_display_name(), output.get_name()));
        item.label.add_style_class_name('display-subtitle');
        item.actor.reactive = false;
        item.actor.can_focus = false;
        this.menu.addMenuItem(item);

        let allowedRotations = this._getAllowedRotations(config, output);
        let currentRotation = output.get_rotation();
        for (let i = 0; i < rotations.length; i++) {
            let [bitmask, name] = rotations[i];
            if (bitmask & allowedRotations) {
                let item = new PopupMenu.PopupMenuItem(_(name));
                if (bitmask & currentRotation)
                    item.setShowDot(true);
                item.connect('activate', Lang.bind(this, function(item, event) {
                    /* ensure config is saved so we get a backup if anything goes wrong */
                    config.save();

                    output.set_rotation(bitmask);
                    try {
                        config.save();
                        this._proxy.ApplyConfigurationRemote(0, event.get_time());
                    } catch (e) {
                        global.logError('Could not save monitor configuration', e);
                    }
                }));
                this.menu.addMenuItem(item);
            }
        }
    }

    _getAllowedRotations(config, output) {
        let retval = 0;

        let current = output.get_rotation();

        for (let i = 0; i < possibleRotations.length; i++) {
            output.set_rotation(possibleRotations[i]);
            if (config.applicable(this._screen)) {
                retval |= possibleRotations[i];
            }
        }

        output.set_rotation(current);

        if (retval.length === 0) {
            // what, no rotation?
            // what's current then?
            retval = current;
        }
        return retval;
    }

};

function main(metadata, orientation, panel_height, instance_id) {
    return new CinnamonXrandrApplet(orientation, panel_height, instance_id);
}
