// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/*
 * Copyright 2011 Red Hat, Inc
 *
 * 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, 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 */

const Atk = imports.gi.Atk;
const Clutter = imports.gi.Clutter;
const Gdm = imports.gi.Gdm;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const St = imports.gi.St;

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

const DomainLoadStatus = {
    INIT : 0,
    SEPARATOR : 1,
    OWN_DOMAIN : 2,
    TRUSTED_DOMAINS : 3,
    DONE : 4,
    ERR : 5
};

const DomainMenuButton = new Lang.Class({
    Name: 'DomainMenuButton',

    _init: function () {
        this._separator = null;
        this.domain_enabled = false;
        this._domains = new Array();
        this._load_config();
    },


    _domainsPush: function(domain) {
        let valid_content = domain.replace(/\s+/g, '');

        if (valid_content.length > 0) {
            if (this._domains.indexOf(valid_content) == -1)
                this._domains.push (valid_content);
        }
    },

    _generate: function() {
        let gearIcon = new St.Icon({ icon_name: 'samba-window',
                                  icon_size: 24
                                 });
        this._button = new St.Button({ style_class: 'login-dialog-session-list-button', //FIXME
                                       reactive: true,
                                       track_hover: true,
                                       can_focus: true,
                                       accessible_name: _("Choose Domain"),
                                       accessible_role: Atk.Role.MENU,
                                       child: gearIcon });

        gearIcon.show();
        this.actor = new St.Bin({ child: this._button });

        this._menu = new PopupMenu.PopupMenu(this._button, 0, St.Side.TOP);
        Main.uiGroup.add_actor(this._menu.actor);
        this._menu.actor.hide();

        this._menu.connect('open-state-changed',
                           Lang.bind(this, function(menu, isOpen) {
                                if (isOpen)
                                    this._button.add_style_pseudo_class('active');
                                else
                                    this._button.remove_style_pseudo_class('active');
                           }));

        this._manager = new PopupMenu.PopupMenuManager({ actor: this._button });
        this._manager.addMenu(this._menu);

        this._button.connect('clicked', Lang.bind(this, function() {
            this._menu.toggle();
        }));

        this._populate();
    },

    _load_config: function() {
        let keyfile = new GLib.KeyFile();
        let path = "/etc/gdm/custom.conf";
        let domain_group = "domains";

    //? Why must use 'try'
        try {
            keyfile.load_from_file(path, GLib.KeyFileFlags.NONE);
        } catch(e) {
        }

        if (!keyfile.has_group(domain_group)) {
            return;
    }

        this.domain_enabled = keyfile.get_boolean(domain_group, 'Enable');
        if (this.domain_enabled) {
            let content = keyfile.get_string(domain_group, 'Domains');
        let domains = content.split(';');
        for (let i = 0; i < domains.length; i++) {
        this._domainsPush(domains[i]);
        }
        this._generate();
    }
    },

    _readStdout: function(data) {
        this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(stream, result) {
            let [line, len] = this._dataStdout.read_line_finish_utf8(result);

            if (line == null) {
                // end of file
                this._stdout.close(null);
        this.loadDomains(data, null);
                return;
            }

        data.push(line);
            this._readStdout(data);
        }));
    },

    loadCommand: function(argv) {
        try {
            let data = new Array();
            let [success, pid, stdin, stdout, stderr] = GLib.spawn_async_with_pipes(null,
                    argv,
                    null,
                    GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
                    null);
            this._stdout = new Gio.UnixInputStream({ fd: stdout, close_fd: true });
            GLib.close(stdin);
            GLib.close(stderr);
            this._dataStdout = new Gio.DataInputStream({ base_stream: this._stdout });
            this._readStdout(data);
        } catch (e) {
            this.loadDomains(null, e);
    }
    },

    loadDomains: function(data, err) {
    /*FIXME: reload every 5 minutes? */
    /*TODO: load the setting file */
        switch (this._status) {
            case DomainLoadStatus.INIT:
                this._status = DomainLoadStatus.SEPARATOR;
                this.loadCommand(["wbinfo", "--separator"]);
                break;
            case DomainLoadStatus.SEPARATOR:
                if (data) {
                    this._separator = data[0];
                    this._status = DomainLoadStatus.OWN_DOMAIN;
                    this.loadCommand(["wbinfo", "--own-domain"]);
                } else {
                    this._status = DomainLoadStatus.ERR;
                    this._menu.removeAll();
                    item = new PopupMenu.PopupMenuItem(_("Cannot receive 'separator'"));
                    item.setSensitive(false);
                    this._menu.addMenuItem(item);
                }
                break;
            case DomainLoadStatus.OWN_DOMAIN:
                if (data) {
                    for (let i = 0; i < data.length; i++) {
                        this._domainsPush(data[i]);
                    }
                }
                this._status = DomainLoadStatus.TRUSTED_DOMAINS;
                this.loadCommand(["wbinfo", "--trusted-domains"]);
                break;
            case DomainLoadStatus.TRUSTED_DOMAINS:
                if (data) {
                    for (let i = 0; i < data.length; i++) {
                        this._domainsPush(data[i]);
                    }
                }
                this._status = DomainLoadStatus.DONE;
                this._menu.removeAll();
                for (let i = 0; i < this._domains.length; i++) {
                    item = new PopupMenu.PopupMenuItem(this._domains[i]);
                        this._menu.addMenuItem(item);
                        item.connect('activate', Lang.bind(this, function(item) {
                        //?? Why it does not work
                        //this.setActiveDomain(this._domains[i]);
                        this.setActiveDomain(item.label.text);
                    }));
                }
                break;
    }
    },

    _populate: function() {
        //TODO Recent domains?
        item = new PopupMenu.PopupMenuItem(_("loading the wbinfos..."));
        item.setSensitive(false);
        this._menu.addMenuItem(item);
        this._status = DomainLoadStatus.INIT;
        this.loadDomains(null, null);
    },

    setActiveDomain: function(domain) {
        this._activeDomain = domain;
        //this.emit('domain-activated', this._activeDomain);
        this.emit('domain-activated');
    },

    getActiveDomain: function(domain) {
        return this._activeDomain;
    },

    getQuestionMessage: function() {
        return _("User for ") + this._activeDomain;
    },

    getHintMessage: function() {
        return _("Contact dliang to get help");
    },

    getDomainUser: function(user) {
        return this._activeDomain + this._separator + user;
    }
});
Signals.addSignalMethods(DomainMenuButton.prototype);
