/* recycleBin.js
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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/>.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

/* exported TrashMenuButton */

const Gettext = imports.gettext;

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

const ExtensionUtils = imports.misc.extensionUtils;

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

const Me = ExtensionUtils.getCurrentExtension();

const _ = Gettext.domain(Me.metadata['gettext-domain']).gettext;

const { PlacesTrashManager } = Me.imports.placesManager;
const { ModalUserDialog } = Me.imports.userDialog;

const MAX_TRASH_ENTRIES = 20;

const PopupTrashMenuItem = GObject.registerClass(
class PopupTrashMenuItem extends PopupMenu.PopupBaseMenuItem {
    _init(info) {
        super._init();
        this._icon = new St.Icon({
            style_class: 'popup-menu-icon',
            x_align: Clutter.ActorAlign.END,
        });
        this.add_child(this._icon);
        this.label = new St.Label({
            text: info.name,
            x_expand: true,
            y_expand: true,
            y_align: Clutter.ActorAlign.CENTER,
        });
        this.add_child(this.label);
        this.label_actor = this.label;
        this._setIcon(info.icon);
        if (info.can_empty) this._addButton('edit-clear-all-symbolic', _('Empty the Trash'), {
            content: 'emptyTrash',
            value: null,
            signal: 'empty',
            callback: () => {
                info.empty();
            },
        });
        if (info.can_restore) this._addButton('edit-undo-symbolic', _('Restore'), {
            content: 'restoreTrashEntry',
            value: info.name,
            signal: 'restore',
            callback: () => {
                info.restore();
            },
        });
        if (info.can_remove) this._addButton('edit-clear-symbolic', _('Delete Permanently'), {
            content: 'deleteTrashEntry',
            value: info.name,
            signal: 'remove',
            callback: () => {
                info.remove();
            },
        });
        this._info = info;
    }

    _addButton(iconName, accessibleName, params) {
        let button = new St.Button({
            style_class: 'button',
            child: new St.Icon({ icon_name: iconName }),
            accessible_name: accessibleName,
            can_focus: true,
            reactive: true,
            track_hover: true,
        });
        button.connect('clicked', () => {
            let dialog = new ModalUserDialog(params.content, params.value);
            dialog.connect(params.signal, params.callback);
            dialog.open();
            Main.overview.hide();
        });
        this.add_child(button);
    }

    _setIcon(icon) {
        if (icon instanceof GObject.Object && GObject.type_is_a(icon, Gio.Icon)) {
            this._icon.gicon = icon;
        } else {
            this._icon.icon_name = icon;
        }
    }

    activate(event) {
        this._info.launch(event.get_time());
        Main.overview.hide();
        super.activate(event);
    }
});

var TrashMenuButton = GObject.registerClass(
class TrashMenuButton extends PanelMenu.Button {
    _init() {
        super._init(0.5, _('Trash'), false);
        this.menu.actor.add_style_class_name('panelmanager-menu');
        this._hbox = new St.BoxLayout({ style_class: 'panel-status-indicators-box' });
        this._icon = new St.Icon({
            style_class: 'system-status-icon',
            icon_name: 'user-trash-symbolic',
        });
        this._hbox.add_child(this._icon);
        this._hbox.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM));
        this.add_child(this._hbox);
        this._placesManager = new PlacesTrashManager();
        this._placesManagerChangedId = this._placesManager.connect('updated', this._reload.bind(this));
        this._reload();
    }

    _addPlaces(menu, kind) {
        let places = this._placesManager.get(kind);
        for (let i = 0; i < places.length; i++) {
            if (i >= MAX_TRASH_ENTRIES) break;
            menu.addMenuItem(new PopupTrashMenuItem(places[i]));
        }
    }

    _onDestroy() {
        this._placesManager.disconnect(this._placesManagerChangedId);
        this._placesManager.destroy();
        super._onDestroy();
    }

    _reload() {
        this.menu.removeAll();
        let visible = this._placesManager.size > 0;
        if (visible) {
            this._addPlaces(this.menu, 'trash');
            let item = new PopupMenu.PopupSubMenuMenuItem(_('Last Trashed'), true);
            item.icon.icon_name = 'user-trash-full';
            this._addPlaces(item.menu, 'trash-item');
            this.menu.addMenuItem(item);
            this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
            item = new PopupMenu.PopupSwitchMenuItem(_('Numbers of objects in the Trash'), false);
            item.setStatus('%s'.format(this._placesManager.size));
            this.menu.addMenuItem(item);
        }
        this.visible = visible;
    }
});
