/* 
	Workspaces Bar
	Copyright Francois Thirioux 2021
	GitHub contributors: @fthx
	License GPL v3
*/


const { Clutter, Gio, GObject, Shell, St } = imports.gi;

const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;

var WORKSPACES_SCHEMA = "org.gnome.desktop.wm.preferences";
var WORKSPACES_KEY = "workspace-names";


var WorkspacesBar = GObject.registerClass(
class WorkspacesBar extends PanelMenu.Button {
	_init() {
		super._init(0.0, 'Workspaces bar');
		
		// define gsettings schema for workspaces names, get workspaces names, signal for settings key changed
		this.workspaces_settings = new Gio.Settings({ schema: WORKSPACES_SCHEMA });
		this.workspaces_names_changed = this.workspaces_settings.connect(`changed::${WORKSPACES_KEY}`, this._update_workspaces_names.bind(this));
	
		// hide Activities button
		this._show_activities(false);
	
		// bar creation
		this.ws_bar = new St.BoxLayout({});
        this._update_workspaces_names();
        this.add_child(this.ws_bar);
        
        // signals for workspaces state: active workspace, number of workspaces
		this._ws_active_changed = global.workspace_manager.connect('active-workspace-changed', this._update_ws.bind(this));
		this._ws_number_changed = global.workspace_manager.connect('notify::n-workspaces', this._update_ws.bind(this));
		this._restacked = global.display.connect('restacked', this._update_ws.bind(this));
		this._windows_changed = Shell.WindowTracker.get_default().connect('tracked-windows-changed', this._update_ws.bind(this));
	}

	// remove signals, restore Activities button, destroy workspaces bar
	_destroy() {
		this._show_activities(true);
		if (this._ws_active_changed) {
			global.workspace_manager.disconnect(this._ws_active_changed);
		}
		if (this._ws_number_changed) {
			global.workspace_manager.disconnect(this._ws_number_changed);
		}
		if (this._restacked) {
			global.display.disconnect(this._restacked);
		}
		if (this._windows_changed) {
			Shell.WindowTracker.get_default().disconnect(this._windows_changed);
		}
		if (this.workspaces_names_changed) {
			this.workspaces_settings.disconnect(this.workspaces_names_changed);
		}
		this.ws_bar.destroy();
		super.destroy();
	}
	
	// hide Activities button
	_show_activities(show) {
		this.activities_button = Main.panel.statusArea['activities'];
		if (this.activities_button) {
			if (show && !Main.sessionMode.isLocked) {
				this.activities_button.container.show();
			} else {
				this.activities_button.container.hide();
			}
		}
	}
	
	// update workspaces names
	_update_workspaces_names() {
		this.workspaces_names = this.workspaces_settings.get_strv(WORKSPACES_KEY);
		this._update_ws();
	}

	// update the workspaces bar
    _update_ws() {
    	// destroy old workspaces bar buttons
    	this.ws_bar.destroy_all_children();
    	
    	// get number of workspaces
        this.ws_count = global.workspace_manager.get_n_workspaces();
        this.active_ws_index = global.workspace_manager.get_active_workspace_index();
		
		// display all current workspaces buttons
        for (let ws_index = 0; ws_index < this.ws_count; ++ws_index) {
			this.ws_box = new St.Bin({visible: true, reactive: true, can_focus: true, track_hover: true});						
			this.ws_box.label = new St.Label({y_align: Clutter.ActorAlign.CENTER});
			if (ws_index == this.active_ws_index) {
				if (global.workspace_manager.get_workspace_by_index(ws_index).n_windows > 0) {
					this.ws_box.label.style_class = 'desktop-label-nonempty-active';
				} else {
					this.ws_box.label.style_class = 'desktop-label-empty-active';
				}
			} else {
				if (global.workspace_manager.get_workspace_by_index(ws_index).n_windows > 0) {
					this.ws_box.label.style_class = 'desktop-label-nonempty-inactive';
				} else {
					this.ws_box.label.style_class = 'desktop-label-empty-inactive';
				}
			}
			if (this.workspaces_names[ws_index]) {
				this.ws_box.label.set_text("  " + this.workspaces_names[ws_index] + "  ");
			} else {
				this.ws_box.label.set_text("  " + (ws_index + 1) + "  ");
			}
			this.ws_box.set_child(this.ws_box.label);
			this.ws_box.connect('button-release-event', () => this._toggle_ws(ws_index) );
	        this.ws_bar.add_actor(this.ws_box);
		}
    }

    // activate workspace or show overview
    _toggle_ws(ws_index) {
		if (global.workspace_manager.get_active_workspace_index() == ws_index) {
			Main.overview.toggle();
		} else {
			global.workspace_manager.get_workspace_by_index(ws_index).activate(global.get_current_time());
		}
    }
});

class Extension {
    constructor() {
    }

    enable() {
    	this.workspaces_bar = new WorkspacesBar();
    	Main.panel.addToStatusArea('workspaces-bar', this.workspaces_bar, 0, 'left');
    }

    disable() {
    	this.workspaces_bar._destroy();
    }
}

function init() {
	return new Extension();
}

