/**
 * File:
 *	include/users/users_plugin_ldap_all.ycp
 *
 * Package:
 *	Configuration of Users
 *
 * Summary:
 *	This is part GUI of UsersPluginLDAPAll - plugin for editing all LDAP
 *	user/group attributes.
 *
 * Authors:
 *	Jiri Suchomel <jsuchome@suse.cz>
 *
 * $Id: users_plugin_ldap_all.ycp 20592 2004-12-17 09:35:25Z jsuchome $
 */


{
    textdomain "users"; // use own textdomain for new plugins

    import "Label";
    import "Popup";
    import "Report";
    import "Wizard";

    import "Ldap";
    import "LdapPopup";
    import "Users";
    import "UsersLDAP";
    import "UsersPluginLDAPAll"; // plugin module

    any ret = nil;
    string func			= "";
    map<string,any> config	= $[];
    map<string,any> data	= $[];

    /* Check arguments */
    if(size(WFM::Args()) > 0 && is(WFM::Args(0), string)) {
	func = (string) WFM::Args(0);
	if(size(WFM::Args()) > 1 && is(WFM::Args(1), map))
	    config = (map<string,any>)WFM::Args(1);
	if(size(WFM::Args()) > 2 && is(WFM::Args(2), map))
	    data = (map<string,any>)WFM::Args(2);
    }
    y2milestone("----------------------------------------");
    y2milestone("users plugin started: LDAPAll");

    y2debug ("func=%1", func);
    y2debug ("config=%1", config);
    y2debug ("data=%1", data);

    if (func == "Summary") {
	ret = UsersPluginLDAPAll::Summary (config, $[]);
    }
    else if (func == "Name") {
	ret = UsersPluginLDAPAll::Name (config, $[]);
    }
    else if (func == "Dialog") {
	// define the dialog for this plugin and return it's contents

	string caption	= UsersPluginLDAPAll::Name (config, $[]);
	string what	= config["what"]:"user";
	string action	= data["what"]:"";

	map<string, any> tmp_data	= $[];
	list<string> object_class = (list<string>)sort (data["objectclass"]:[]);

	// helptext 1/3
	string help_text = _("<p>
Here, see the table of all allowed attributes for the current LDAP entry that were not set in previous dialogs.</p>") +

	// helptext 1/3 (don't translate objectclass"),
        // %1 is list of values
	sformat (_("<p>
The list of attributes is given by the value of \"objectclass\"
(which is currently:
<br>%1).
</p>
"), mergestring (object_class, ",<br>")) +

	// helptext 3/3
	_("<p>
Edit each attribute using <b>Edit</b>. Some attributes 
could be required, as defined in the user template in the <b>LDAP Client Module</b>.</p>
");

        list items			= [];
        list used_attributes	= [];
        list new_attributes		= [];
        boolean modified		= false;

	// which LDAP keys should not be edited here
	// (either because they were edited before or it is to hard to edit
	// them (objectclass, DN)
	list do_not_show_keys	= (what == "user") ?
	[ "uid", "username", "uidnumber", "homedirectory",
	// "givenname", "sn",
	"userpassword", "objectclass", "loginshell", "gidnumber",
	"shadowlastchange", "shadowwarning", "shadowinactive", "shadowexpire",
	"shadowmin", "shadowmax", "shadowflag"
	] :
	// and now for groups
	[ "groupname", "gidnumber", "userpassword", "objectclass", "userlist",
	  "cn", Ldap::member_attribute
	];

	// keys in user's map which are not saved anywhere
	list internal_keys = (what == "user") ?
	    UsersLDAP::GetUserInternal () : UsersLDAP::GetGroupInternal ();

	// show only attributes allowed by schema
	list allowed_attrs= Ldap::GetObjectAttributes (object_class);

	// do not allow editing of binary values (perl converts them to string)
	list binary_attrs = [ "jpegphoto", "usercertificate" ];

	// generate table items from already existing values
        foreach (string attr, any val, data, ``{
	    string at = tolower (attr);
	    if (contains (internal_keys, at))
		return;
	    if (contains (do_not_show_keys, at))
		return;
	    if (!contains (allowed_attrs, at))
		return;
	    if (is (val, map) || val == nil)
		return;
	    list<string> value = [];
	    if (is (val, list))
	    {
		value = (list<string>)val;
	    }
	    if (contains (binary_attrs, at) || is (val, byteblock) ||
		(is (val, list) && is (value[0]:nil, byteblock)))
	    {
		y2warning ("binary value (%1) cannot be edited", at);
		return;
	    }
	    else if (is (val, integer))
	    {
		value = [ sformat ("%1", val) ];
		data [at] = value;
	    }
	    else if (is (val, string))
	    {
		value = [ (string)val ];
		data [at] = value;
	    }
	    used_attributes = add (used_attributes, at);
	    items = add (items,`item (`id(at), at, mergestring(value,",")));
	});

	// generate table items with empty values
	// (not set for this user/group yet)
	// we need to read available attributes from Ldap
	foreach (string class, object_class, {
	    foreach (string at,(list<string>)Ldap::GetAllAttributes (class), {
		// remove already used (uid, uidnumber, homedirectory etc.)
		if (!haskey (data, at) &&
		    !contains (do_not_show_keys, at))
		{
		    data[at] = [];
		    new_attributes = add (new_attributes, at);
		    items = add (items, `item (`id(at), at, ""));
		}
	    });
	});

	term contents = `HBox(`HSpacing (1.5), `VBox(
	    `VSpacing(0.5),
	    `Table(`id(`table), `opt(`notify), `header(
		// table header 1/2
		_("Attribute") + "  ",
		// table header 2/2
		_("Value")),
		items),
	    `HBox (
		`PushButton(`id(`edit), `opt(`key_F4), Label::EditButton()),
		`HStretch()
	    ),
	    `VSpacing (0.5)
	    ),
	    `HSpacing (1.5)
	);

	Wizard::CreateDialog ();
        Wizard::SetDesktopIcon("users");

	// dialog caption
	Wizard::SetContentsButtons(_("Additional LDAP Settings"),
	    contents, help_text, Label::CancelButton(), Label::AcceptButton());

	Wizard::HideAbortButton ();

	if (size (items) == 0)
	    UI::ChangeWidget (`id(`edit), `Enabled, false);

	ret = `next;
        UI::SetFocus (`id(`table));
	repeat
	{
	    ret = UI::UserInput();
	    if ( ret == `edit || ret == `table)
	    {
		string attr		=
		    (string) UI::QueryWidget (`id(`table), `CurrentItem);
		list<string> value	= tmp_data [attr]:data[attr]:[];
		value			= LdapPopup::EditAttribute ($[
		    "attr"          : attr,
		    "value"         : value,
		    "single"        : Ldap::SingleValued (attr)
		]);
		if (value == tmp_data [attr]:data[attr]:[])
		{
		    ret = `notnext;
		    continue;
		}
		UI::ChangeWidget (`id(`table),`Item(attr,1),
		    mergestring(value,","));
		tmp_data [attr] = value;
	    }
	    if ( ret == `next )
	    {
		string err = UsersPluginLDAPAll::Check (
		    config,
		    (map<string,any>) union (data, tmp_data));

		if (err != "")
		{
		    Report::Error (err);
		    ret = `notnext;
		    continue;
		}

		if (tmp_data == $[])
		{
		    break;
		}
		// if this plugin wasn't in default set, we must save its name
		if (!contains (data["plugins"]:[], "UsersPluginLDAPAll"))
		{
		    tmp_data["plugins"] = add (tmp_data["plugins"]:[],
			"UsersPluginLDAPAll");
		}
		if (data["what"]:"" == "edit_user")
		{
		    Users::EditUser (tmp_data);
		}
		else if (data["what"]:"" == "add_user")
		{
		    Users::AddUser (tmp_data);
		}
		else if (data["what"]:"" == "edit_group")
		{
		    Users::EditGroup (tmp_data);
		}
		else if (data["what"]:"" == "add_group")
		{
		    Users::AddGroup (tmp_data);
		}
	    }
	} until (is(ret,symbol) &&
	    contains ([`next, `abort, `back, `cancel], (symbol) ret));

	Wizard::CloseDialog ();
    }
    /* unknown function */
    else {
	y2error("unknown function: %1", func);
	ret = false;
    }

    y2debug ("ret=%1", ret);
    y2milestone("users plugin finished");
    y2milestone("----------------------------------------");

    return ret;
}
