const { Atk, Clutter, GObject, Pango, St } = imports.gi;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
const Signals = imports.signals;

var HeadsUpMessageBodyLabel = GObject.registerClass({
}, class HeadsUpMessageBodyLabel extends St.Label {
    _init(params) {
        super._init(params);

        this.clutter_text.single_line_mode = false;
        this.clutter_text.line_wrap = true;
    }

    vfunc_get_preferred_width(forHeight) {
        let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);

        let [labelMinimumWidth, labelNaturalWidth] = super.vfunc_get_preferred_width(forHeight);

        labelMinimumWidth = Math.min(labelMinimumWidth, .75 * workArea.width);
        labelNaturalWidth = Math.min(labelNaturalWidth, .75 * workArea.width);

        return [labelMinimumWidth, labelNaturalWidth];
    }

    vfunc_get_preferred_height(forWidth) {
        let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
        let labelHeightUpperBound = .25 * workArea.height;

        this.clutter_text.single_line_mode = true;
        this.clutter_text.line_wrap = false;
        let [lineHeight] = super.vfunc_get_preferred_height(-1);
        let numberOfLines = Math.floor(labelHeightUpperBound / lineHeight);
        numberOfLines = Math.max(numberOfLines, 1);

        let labelHeight = lineHeight * numberOfLines;

        this.clutter_text.single_line_mode = false;
        this.clutter_text.line_wrap = true;
        let [labelMinimumHeight, labelNaturalHeight] = super.vfunc_get_preferred_height(forWidth);

        labelMinimumHeight = Math.min(labelMinimumHeight, labelHeight);
        labelNaturalHeight = Math.min(labelNaturalHeight, labelHeight);

        return [labelMinimumHeight, labelNaturalHeight];
    }

    vfunc_allocate(box, flags) {
        if (!this.visible)
            return;

        super.vfunc_allocate(box, flags);
    }
});

var HeadsUpMessage = GObject.registerClass({
}, class HeadsUpMessage extends St.Button {
    _init(heading, body) {
        super._init({
            style_class: 'message',
            accessible_role: Atk.Role.NOTIFICATION,
            can_focus: false,
        });

        Main.layoutManager.addChrome(this, { affectsInputRegion: true });

        this.add_style_class_name('heads-up-display-message');

        this._panelAllocationId = Main.layoutManager.panelBox.connect ("notify::allocation", this._alignWithPanel.bind(this));
        this.connect("notify::allocation", this._alignWithPanel.bind(this));

        this._messageTraySnappingId = Main.messageTray.connect ("notify::y", () => {
            if (!this.visible)
                return;

            if (!Main.messageTray.visible)
                return;

            if (Main.messageTray.y >= this.y && Main.messageTray.y < this.y + this.height)
                Main.messageTray.y = this.y + this.height;
        });


        let contentsBox = new St.BoxLayout({ style_class: 'heads-up-message-content',
                                             vertical: true,
                                             x_align: Clutter.ActorAlign.CENTER });
        this.add_actor(contentsBox);

        this.headingLabel = new St.Label({ style_class: 'heads-up-message-heading',
                                           x_expand: true,
                                           x_align: Clutter.ActorAlign.CENTER });
        this.setHeading(heading);
        contentsBox.add_actor(this.headingLabel);
        this.contentsBox = contentsBox;

        this.bodyLabel = new HeadsUpMessageBodyLabel({ style_class: 'heads-up-message-body',
                                                       x_expand: true,
                                                       y_expand: true });
        contentsBox.add_actor(this.bodyLabel);

        this.setBody(body);
        this.bodyLabel.clutter_text.label = this.bodyLabel;
    }

    _alignWithPanel() {
        if (!this.visible)
            return;

        this.x = Main.panel.actor.x;
        this.x += Main.panel.actor.width / 2;
        this.x -= this.width / 2;
        this.x = Math.floor(this.x);
        this.y = Main.panel.actor.y + Main.panel.actor.height;
        this.queue_relayout();
    }

    setHeading(text) {
        if (text) {
            let heading = text ? text.replace(/\n/g, ' ') : '';
            this.headingLabel.text = heading;
            this.headingLabel.visible = true;
        } else {
            this.headingLabel.text = text;
            this.headingLabel.visible = false;
        }
    }

    setBody(text) {
        this.bodyLabel.text = text;
        if (text) {
            this.bodyLabel.visible = true;
        } else {
            this.bodyLabel.visible = false;
        }
    }

    destroy() {
        if (this._panelAllocationId) {
            Main.layoutManager.panelBox.disconnect(this._panelAllocationId);
            this._panelAllocationId = 0;
        }

        if (this._messageTraySnappingId) {
            Main.messageTray.disconnect(this._messageTraySnappingId);
            this._messageTraySnappingId = 0;
        }

        super.destroy();
    }
});
