/**
 * File:	include/dhcp-server/widgets.ycp
 * Package:	Configuration of dhcp-server
 * Summary:	Widgets
 * Authors:	Jiri Srain <jsrain@suse.cz>
 *
 * $Id: widgets.ycp 21861 2005-02-23 11:49:24Z jsrain $
 */

{

    textdomain "dhcp-server";

    import "CWM";
    import "CWMTsigKeys";
    import "DhcpServer";
    import "Hostname";
    import "IP";
    import "Label";
    import "LogView";
    import "Popup";
    import "TablePopup";


// pre-declarations

global define void configTreeInit (string id);
global define symbol chrootHandle (string id, map event);
global define symbol ldapHandle (string id, map event);


    /**
      * Function for deleting entry from section
      * Used for all (global, host, subnet) section due to the same location
      *  of data
      * @param opt_id any option id
      * @param key string option key
      * @return boolean true if was really deleted
      */
    global define boolean commonTableEntryDelete (any opt_id, string key) ``{
	if (! is (opt_id, string))
	    return false;
	integer index = tointeger (
	    regexpsub ((string)opt_id, "^[a-z]+ ([0-9]+)$", "\\1"));
	if (substring (key, 0, 7) == "option ")
	{
	    current_entry_options[index] = nil;
	    current_entry_options = filter (map<string,string> o,
		current_entry_options,
		``( o != nil));
	}
	else
	{
	    current_entry_directives[index] = nil;
	    current_entry_directives = filter (map<string,string> d,
		current_entry_directives,
		``( d != nil));
	}
	return true;
    }

    /**
      * Create list of identifiers of etries that should be present in the table
      * @param descr map description of the table
      * @return list of identifiers of entries of the table
      */
    global define list getTableContents (map descr) ``{
	integer index = -1;
	list<string> opts = maplist (map m, current_entry_options, ``{
	    index = index + 1;
	    return sformat ("option %1", index);
	});

	index = -1;
	list<string> dirs = maplist (map m, current_entry_directives, ``{
	    index = index + 1;
	    if (m["key"]:"" != "zone")
		return sformat ("directive %1", index);
	    return nil;
	});
	return filter (string id, (list<string>)merge (dirs, opts),
	    ``(id != nil));
    }

    /**
      * Transform table entry id to option id
      * @param table map table description
      * @param id any entry id
      * @return string option key
      */
    global define string id2key (map table, any id) ``{
	if (! is (id, string))
	    return "";
	string strid = (string)id;
	if (substring (strid, 0, 7) == "option ")
	{
	    integer index = tointeger (substring (strid, 7));
	    return sformat ("option %1",
		current_entry_options[index, "key"]:"");
	}
	else if (substring (strid, 0, 10) == "directive ")
	{
	    integer index = tointeger (substring (strid, 10));
	    return current_entry_directives[index, "key"]:"";
	}
	return strid;
    }

    /**
      * Get the popup widget description map
      * @param opt_key string option key
      * @return map popup description map
      */
    global define map key2descr (string opt_key) ``{
	map ret = (map)(popups[opt_key]:nil);
	if (ret != nil)
	    return ret;
	return $[
                "init" : commonPopupInit,
                "store" : commonPopupSave,
	];
    }

    /**
      * Get map of widget
      * @param add_values list of values to be offered via the add button
      * @return map of widget
      */
    global define map<string,any> getOptionsTableWidget (list add_values) ``{
	map<string,any> ret = TablePopup::CreateTableDescr (
	    $["add_delete_butons" : true, "up_down_buttons" : false],
	    $[
		"init": TablePopup::TableInitWrapper,
		"handle": TablePopup::TableHandleWrapper,
		"options": popups,
		"id2key": id2key,
		"ids": getTableContents,
		"help": HELPS["options_table"]:"",
		"fallback" : $[
		    "init": commonPopupInit,
		    "store": commonPopupSave,
		    "summary": commonTableEntrySummary,
		],
		"option_delete": commonTableEntryDelete,
		"add_items":  add_values,
		"add_items_keep_order" : true,
	    ]
	);
	return ret;
    }


    /**
      * Ask for exit without saving
      * @return event that should be handled, nil if user canceled the exit
      */
    global define boolean confirmAbort () ``{
        return Popup::YesNo (
// Yes-No popup
_("Really leave the DHCP server configuration without saving?
All changes will be lost."));
    }

    /**
      * Check whether settings were changed and if yes, ask for exit
      * without saving
      * @return event that should be handled, nil if user canceled the exit
      */
    global define boolean confirmAbortIfChanged () ``{
	if (! DhcpServer::GetModified ())
	    return true;
	return confirmAbort ();
    }

/**
 * Enable or disable a widget according the current status of the service
 * @param id string widget id
 * @param event map event that caused storing process
 */
global define void dhcpEnabledOrDisabled (string id, map event) ``{
    any ev_id = event["ID"]:nil;
    if (ev_id == "boot" || ev_id == "never")
    {
	boolean enabled = UI::QueryWidget (`id ("start"), `CurrentButton)
	    != "never";
	UI::ChangeWidget (`id (id), `Enabled, enabled);
    }
}

/**
 * Initialize the widget
 * @param id any widget id
 */
global define void startInit (string id) ``{
    boolean ss = DhcpServer::GetStartService();
    UI::ChangeWidget (`id ("start"), `Value, ss);
}

/**
 * Store settings of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 */
global define void startStore (string id, map event) ``{
    boolean ss = (boolean)UI::QueryWidget (`id ("start"), `Value);
    DhcpServer::SetStartService (ss);
}

/**
 * Handle function of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 * @return symbol always nil
 */
global define symbol startHandle (string id, map event) ``{
    boolean start = (boolean)UI::QueryWidget (`id ("start"), `Value);
    if (start != DhcpServer::GetStartService ())
	DhcpServer::SetModified ();
    return nil;
}

// chroot widget

/**
 * Initialize the widget
 * @param id any widget id
 */
global define void chrootInit (string id) ``{
    boolean ss = DhcpServer::GetChrootJail();
    UI::ChangeWidget (`id (id), `Value, ss);
    chrootHandle (id, $[ "ID" : "start" ]);
}

/**
 * Store settings of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 */
global define void chrootStore (string id, map event) ``{
    boolean ss = (boolean)UI::QueryWidget (`id (id), `Value);
    DhcpServer::SetChrootJail (ss);
}

/**
 * Handle function of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 * @return symbol always nil
 */
global define symbol chrootHandle (string id, map event) ``{
    if (event["ID"]:nil == "start")
    {
	boolean en = (boolean)UI::QueryWidget (`id ("start"), `Value);
	UI::ChangeWidget (`id (id), `Enabled, en);
	return nil;
    }
    boolean start = (boolean)UI::QueryWidget (`id (id), `Value);
    if (start != DhcpServer::GetChrootJail ())
        DhcpServer::SetModified ();
    return nil;
}

// ldap widget

/**
 * Initialize the widget
 * @param id any widget id
 */
global define void ldapInit (string id) ``{
    boolean ul = DhcpServer::GetUseLdap();
    UI::ChangeWidget (`id (id), `Value, ul);
    ldapHandle (id, $[ "ID" : "start" ]);
}

/**
 * Set the LDAP usage, reinitalize LDAP support
 * @param use_ldap boolean true if LDAP is to be used
 */
global define void SetUseLdap (boolean use_ldap) {
    DhcpServer::SetUseLdap (use_ldap);
    if (! Mode::config ())
    {
	DhcpServer::InitYapiConfigOptions ($["use_ldap" : use_ldap]);
	DhcpServer::LdapInit ([], true);
	DhcpServer::CleanYapiConfigOptions ();
    }
}

/**
 * Handle function of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 * @return symbol always nil
 */
global define symbol ldapHandle (string id, map event) ``{
    if (event["ID"]:nil == "start")
    {
	boolean en = (boolean)UI::QueryWidget (`id ("start"), `Value);
	UI::ChangeWidget (`id (id), `Enabled, en);
	return nil;
    }
    boolean ldap = (boolean)UI::QueryWidget (`id (id), `Value);
    if (ldap != DhcpServer::GetUseLdap ())
    {
	SetUseLdap (ldap);
	ldap = DhcpServer::GetUseLdap ();
	UI::ChangeWidget (`id (id), `Value, ldap);
    }
    return nil;
}


/**
 * Initialize the widget
 * @param id any widget id
 */
global define void OpenFirewallInit (string id) ``{
    boolean enabled = Service::Enabled("SuSEfirewall2_init");
    boolean open = DhcpServer::GetOpenFirewall ();
    UI::ChangeWidget (`id (id), `Enabled, enabled);
    UI::ChangeWidget (`id (id), `Value, open);
}

/**
 * Store settings of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 */
global define void OpenFirewallStore (string id, map event) ``{
    boolean open = (boolean)UI::QueryWidget (`id (id), `Value);
    DhcpServer::SetOpenFirewall (open);
    DhcpServer::SetModified ();
}

global boolean OpenFirewallValidate (string id, map event) {
    boolean open = (boolean)UI::QueryWidget (`id (id), `Value);
    boolean enabled = Service::Enabled("SuSEfirewall2_init");
    if (enabled && ! open)
    {
	// yes-no popup
	if (! Popup::YesNo (_("The port in firewall is not open. The DHCP server
will not be able to serve your network.
Continue?")))
	{
	    return false;
	}
    }
    return true;
}


/**
 * Handle function of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 * @return symbol always nil
 */
global define symbol configTreeHandle (string id, map event) ``{
    if (Mode::config () && (
	event["ID"]:nil == `log || event["ID"]:nil == `interfaces
	|| event["ID"]:nil == `tsig_keys))
    {
	// popup message
	Popup::Message (_("This function is not available during
preparation for autoinstallation."));
	return nil;
    }
    boolean enabled = (boolean)UI::QueryWidget (`id ("start"), `Value);
    if (event["ID"]:nil == "start")
    {
        UI::ChangeWidget (`id ("configtree"), `Enabled, enabled);
        UI::ChangeWidget (`id (`adv), `Enabled, enabled);
        UI::ChangeWidget (`id (`edit), `Enabled, enabled);
    }
    if (event["ID"]:nil == `log)
    {
	LogView::Display ($[
	    "file" : "/var/log/messages",
	    "grep" : "dhcpd",
	    "save" : true,
	    "actions" : [
		// menubutton entry, try to keep short
		[ _("Restart DHCP Server"),
		    RestartDhcpDaemon ],
		// menubutton entry, try to keep short
		[ _("Save Settings and Restart DHCP Server"),
		    DhcpServer::Write ],
	    ],
	]);
	return nil;
    }
    if (event["ID"]:nil == `interfaces)
	return `interfaces;
    if (event["ID"]:nil == `tsig_keys)
	return `tsig_keys;
    string current_item = (string)
	UI::QueryWidget (`id ("configtree"), `CurrentItem);
    if (current_item == " " || ! enabled)
    {
	UI::ChangeWidget (`id (`delete), `Enabled, false);
//	UI::ChangeWidget (`id (`move), `Enabled, false);
    }
    else
    {
	UI::ChangeWidget (`id (`delete), `Enabled, true);
//	UI::ChangeWidget (`id (`move), `Enabled, true);
    }
    map<string,string> selected = key2typeid (current_item);
    if (selected == nil)
    {
	y2error ("Unexistent entry selected");
	return nil;
    }
    string sel_type = selected["type"]:"";
    if (sel_type == "pool" || sel_type == "class" || sel_type == "host"
	|| ! enabled)
    {
	UI::ChangeWidget (`id (`add), `Enabled, false);
    }
    else
    {
	UI::ChangeWidget (`id (`add), `Enabled, true);
    }

    if (event["ID"]:nil == "configtree"
	&& event["EventReason"]:nil == "Activated")
    {
	event["ID"] = `edit;
    }

    if (event["ID"]:nil == `add)
    {
	original_entry_type = "";
	original_entry_id = "";
	parent_type = selected["type"]:"";
	parent_id = selected["id"]:"";
	current_entry_options = [];
	current_entry_directives = [];
	current_entry_type = "";
	current_entry_id = "";
	current_operation = `add;
	return `add;
    }
    else if (event["ID"]:nil == `edit)
    {
	current_entry_type = selected["type"]:"";
	current_entry_id = selected["id"]:"";
	current_entry_options = DhcpServer::GetEntryOptions (
	    current_entry_type,
	    current_entry_id);
	current_entry_directives = DhcpServer::GetEntryDirectives (
	    current_entry_type,
	    current_entry_id);

	original_entry_type = current_entry_type;
	original_entry_id = current_entry_id;
	parent_type = "";
	parent_id = "";
	current_operation = `edit;

	return `edit;
    }
    else if (event["ID"]:nil == `delete)
    {
	DhcpServer::DeleteEntry (selected["type"]:"", selected["id"]:"");
	configTreeInit (id);
    }
    else if (event["ID"]:nil == `move)
    {
	return nil;
// TODO move button
    }
/*    if (event["ID"]:nil == `add || event["ID"]:nil == `edit)
    {
	current_ddns_key_file = DhcpServer::GetDDNSFileName ();
	current_ddns_key_create = DhcpServer::GetDDNSFileCreate ();
    }*/

    return nil;
}

/**
 * Initialize the widget
 * @param id any widget id
 */
global define void configTreeInit (string id) ``{
    list items = getItems ("", "");
    items = [
	`item (`id (" "), _("Global Options"), true, items)
    ];
    UI::ReplaceWidget (`configtree_rp, `Tree (
	`id ("configtree"),
	`opt (`notify),
	// tree widget
	_("&Configured Declarations"),
        items
    ));
    UI::ChangeWidget (`id ("configtree"), `CurrentItem, " ");
    configTreeHandle (id, $["ID" : "start"]);
    return;
}

/**
 * Initialize the widget
 * @param id any widget id
 */
global define void subnetInit (string id) ``{
    list<string> l = regexptokenize (current_entry_id,
	"^[ \t]*([^ \t]+)[ \t]*netmask[ \t]*([^ \t]+)[ \t]*$");
    UI::ChangeWidget (`id (`subnet), `Value, l[0]:"");
    UI::ChangeWidget (`id (`netmask), `Value, l[1]:"");
}

/**
 * Store settings of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 */
global define void subnetStore (string id, map event) ``{
    string id = sformat ("%1 netmask %2",
	(string)UI::QueryWidget (`id (`subnet), `Value),
	(string)UI::QueryWidget (`id (`netmask), `Value));
    current_entry_id = id;
}

/**
 * Initialize the widget
 * @param id any widget id
 */
global define void idInit (string id) ``{
    UI::ChangeWidget (`id (id), `Value, current_entry_id);
}

/**
 * Store settings of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 */
global define void idStore (string id, map event) ``{
    current_entry_id = (string)
	UI::QueryWidget (`id (id), `Value);
}

/**
 * Initialize the widget
 * @param id string widget id
 */
global define void interfacesInit (string id) ``{
    list ifaces = DhcpServer::GetAllowedInterfaces ();
    UI::ChangeWidget (`id (id), `SelectedItems, ifaces);
}

/**
 * Store settings of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 */
global define void interfacesStore (string id, map event) ``{
    list ifaces = (list)UI::QueryWidget (`id (id), `SelectedItems);
    list<string> interfaces = (list<string>)ifaces;
    DhcpServer::SetAllowedInterfaces (interfaces);
    DhcpServer::SetModified ();
}

/**
 * Initialize the widget
 * @param id any widget id
 */
global define void DynDnsButtonInit (string id) ``{
    UI::ReplaceWidget (`_tp_table_repl, `PushButton (`id ("dyn_dns_button"),
	// push button
	_("&Dynamic DNS")));
}

/**
 * Handle events of the widget
 * @param id string widget id
 * @param event map event that is handled
 * @return symbol for WS
 */
global define symbol DynDnsButtonHandle (string id, map event) ``{
    if (Mode::config ())
    {
	// popup message
	Popup::Message (_("This function is not available during
preparation for autoinstallation."));
	return nil;
    }
    if (size (DhcpServer::ListTSIGKeys ()) == 0)
	return `tsig_keys;
    return `dyn_dns;
}

/**
 * Handle events of the widget
 * @param id string widget id
 * @param event map event that is handled
 * @return symbol for WS
 */
global define symbol DDNSZonesHandle (string id, map event) ``{
    boolean enabled = (boolean)UI::QueryWidget (`id ("ddns_enable"), `Value);
    UI::ChangeWidget (`id ("zone"), `Enabled, enabled);
    UI::ChangeWidget (`id ("zone_ip"), `Enabled, enabled);
    UI::ChangeWidget (`id ("reverse_zone"), `Enabled, enabled);
    UI::ChangeWidget (`id ("reverse_ip"), `Enabled, enabled);
    UI::ChangeWidget (`id ("ddns_key"), `Enabled, enabled);
    UI::ChangeWidget (`id ("ddns_rev_key"), `Enabled, enabled);
    UI::ChangeWidget (`id (`update_ddns_glob), `Enabled, enabled);
    return nil;
}

/**
 * Initialize the widget
 * @param id string widget id
 */
global define void DDNSZonesInit (string id) ``{
    string zone = "";
    string ip = "";
    string rev_zone = "";
    string rev_ip = "";
    string key = "";
    string rev_key = "";
    UI::ChangeWidget (`id ("zone"), `ValidChars,
	Hostname::ValidCharsDomain);
    UI::ChangeWidget (`id ("zone_ip"), `ValidChars,
	Hostname::ValidCharsDomain);
    UI::ChangeWidget (`id ("reverse_zone"), `ValidChars,
	Hostname::ValidCharsDomain);
    UI::ChangeWidget (`id ("reverse_ip"), `ValidChars,
	Hostname::ValidCharsDomain);
    boolean found_ddns = false;
    foreach (map d, current_entry_directives, ``{
	if (d["key"]:"" == "zone")
	{
	    string value = (string)(d["value"]:"");
	    list<string> l = regexptokenize (value, "^[ \t]*([^ \t]+)[ \t]*\\{[ \t]*primary[ \t]+([^ \t]+)[ \t]*;[ \t]*key[ \t]+([^ \t]+)[ \t]*;[ \t]*\}[ \t]*$");
	    if (size (l) == 3)
	    {
		string z = l[0]:"";
		string a = l[1]:"";
		string k = l[2]:"";
		if (issubstring (z, "in-addr.arpa"))
		{
		    rev_zone = z;
		    rev_ip = a;
		    rev_key = k;
		}
		else
		{
		    zone = z;
		    ip = a;
		    key = k;
		}
		found_ddns = true;
	    }
	}
    });

    list<map<string,string> > updater_keys_m = DhcpServer::ListTSIGKeys ();
    list<string> updater_keys = maplist (map m, updater_keys_m, ``(
	m["key"]:""
    ));

    UI::ReplaceWidget (`ddns_key_rp, `ComboBox (`id("ddns_key"),
	// combo box
	_("Forward Zone TSIG &Key"), updater_keys));
    UI::ReplaceWidget (`rev_ddns_key_rp, `ComboBox (`id("ddns_rev_key"),
	// combo box
	_("Reverse Zone TSIG &Key"), updater_keys));

    if (found_ddns)
    {
	UI::ChangeWidget (`id ("zone"), `Value, zone);
	UI::ChangeWidget (`id ("zone_ip"), `Value, ip);
	UI::ChangeWidget (`id ("reverse_zone"), `Value, rev_zone);
	UI::ChangeWidget (`id ("reverse_ip"), `Value, rev_ip);
	UI::ChangeWidget (`id ("ddns_key"), `Value, key);
	UI::ChangeWidget (`id ("ddns_rev_key"), `Value, rev_key);
    }
    UI::ChangeWidget (`id (`update_ddns_glob), `Value,
	DhcpServer::GetAdaptDdnsSettings ());
    UI::ChangeWidget (`id ("ddns_enable"), `Value, found_ddns);
    DDNSZonesHandle (id, $[]);
}

/**
 * Validate the widget
 * @param id string widget id
 * @param event map event that is handled
 * @return boolean true if validation succeeded
 */
global define boolean DNSZonesValidate (string id, map event) {
    if (! (boolean)UI::QueryWidget (`id ("ddns_enable"), `Value))
    {
	return true;
    }
    boolean ret = true;
    foreach (string w, ["zone", "zone_ip", "reverse_zone", "reverse_ip"], {
	string value = (string)UI::QueryWidget (`id (w), `Value);
	if ((w == "zone" || w == "reverse_zone")
	    && regexpmatch (value, "^.*\\.$"))
	{
	    value = regexpsub (value, "^(.*)\\.$", "\\1");
	}
	if (! (Hostname::CheckFQ (value)
	    || (contains (["zone_ip", "reverse_ip"], w)
		&& IP::Check4 (value))))
	{
	    UI::SetFocus (`id (w));
	    Report::Error (Hostname::ValidFQ());
	    ret = false;
	    break;
	}
    });
    return ret;
}


/**
 * Store settings of the widget
 * @param id string widget id
 * @param event map event that caused storing process
 */
global define void DDNSZonesStore (string id, map event) ``{
    current_entry_directives = filter (map<string,string> m,
	current_entry_directives, ``(
	m["key"]:"" != "zone"
    ));
    if ((boolean)UI::QueryWidget (`id ("ddns_enable"), `Value))
    {
	string zone = (string)UI::QueryWidget (`id ("zone"), `Value);
	string ip = (string)UI::QueryWidget (`id ("zone_ip"), `Value);
	string rev_zone = (string)UI::QueryWidget (`id ("reverse_zone"),`Value);
	string rev_ip = (string)UI::QueryWidget (`id ("reverse_ip"), `Value);
	string key = (string)UI::QueryWidget (`id ("ddns_key"), `Value);
	string rev_key = (string)UI::QueryWidget (`id ("ddns_rev_key"), `Value);
	if (ip == "")
	    ip = "127.0.0.1";
	if (rev_ip == "")
	    rev_ip = "127.0.0.1";
	if (zone != "")
	{
	    if (! regexpmatch (zone, "^.*\\.$"))
		zone = zone + ".";
	    current_entry_directives = add (current_entry_directives, $[
		"key" : "zone",
		"value" : sformat ("%1 { primary %2; key %3; }",
		    zone, ip, key),
	    ]);
	}
	if (rev_zone != "")
	{
	    if (! regexpmatch (rev_zone, "^.*\\.$"))
		rev_zone = rev_zone + ".";
	    current_entry_directives = add (current_entry_directives, $[
		"key" : "zone",
		"value" : sformat ("%1 { primary %2; key %3; }",
		    rev_zone, rev_ip, rev_key),
	    ]);
	}
	boolean ug = (boolean)UI::QueryWidget (`id (`update_ddns_glob), `Value);
	DhcpServer::SetAdaptDdnsSettings (ug);
    }
}

/**
 * Handle events of the widget
 * @param id string widget id
 * @param event map event that is handled
 * @return symbol for WS
 */
global define symbol KeyFileBrowseButtonHandle (string id, map event) ``{
    string filename = (string)UI::QueryWidget (`id ("key_filename"), `Value);
    filename = UI::AskForExistingFile (filename, "",
	// popup headline
	_("Select File with Authentication Key"));
    if (filename != nil)
	UI::ChangeWidget (`id ("key_filename"), `Value, filename);
    return nil;
}

/**
 * Validate the widget
 * @param id string widget id
 * @param event map event that is handled
 * @return boolean true if validation succeeded
 */
global define boolean EmptyOrIpValidate (string id, map event) ``{
    string val = (string)UI::QueryWidget (`id (id), `Value);
    if (val == "" || IP::Check4 (val))
	return true;
    Popup::Message (IP::Valid4 ());
    UI::SetFocus (`id (id));
    return false;
}



define list<string> optsort (list<string> options) ``{
    options = toset (options);
    options = sort (options);
    list<string> o1
	= filter (string o, options, ``(regexpmatch (o, "^option .+$")));
    list<string> o2
	= filter (string o, options, ``(! regexpmatch (o, "^option .+$")));
    return (list<string>)merge (o2, o1);
}

define void ConfigSummaryInit (string key) {
    UI::ChangeWidget (`id (key), `Value, sformat (
	"<ul><li>%1</li></ul>",
	mergestring (DhcpServer::Summary (["no_start"]), "</li>\n<li>")
    ));
}

define symbol AllSettingsButtonHandle (string key, map event) {
    return `main;
}

/**
  * Initialize widgets
  * Create description map and copy it into appropriate variable of the
  *  DhcpServer module
  */
global define void InitWidgets () ``{
    list<string> options = [
"option subnet-mask",
"option broadcast-address",
"option routers",
"option static-routes",
"option domain-name",
"option domain-name-servers",
"option host-name",
"option root-path",
"option tftp-server-name",
"option bootfile-name",
"option dhcp-server-identifier",
"option time-servers",
"option ntp-servers",
"option log-servers",
"option lpr-servers",
"option font-servers",
"option x-display-managers",
"option smtp-server",
"option pop-server",
"option irc-server",
"option nis-domain",
"option nis-servers",
"option nisplus-domain",
"option nisplus-servers",
"option interface-mtu",
"option vendor-encapsulated-options",
"option vendor-class-identifier",
"option netbios-name-servers",
"option netbios-dd-server",
"option netbios-node-type",
"option netbios-scope",
    ];

    list<string> common_commands = [
"max-lease-time",
"default-lease-time",
"filename",
"next-server",
"allow",
"deny",
    ];

    list<string> global_commands = [
"authoritative",
"ddns-update-style",
"ddns-updates",
"log-facility",
    ];

    list<string> subnet_commands = [
"range",
    ];

    list<string> host_commands = [
"hardware",
"fixed-address",
    ];

    list<string> class_commands = [
"match",
    ];

    list<string> shared_net_commands = [

    ];

    list<string> pool_commands = [
	"range",
    ];

    list<string> group_commands = [

    ];

    common_commands = optsort ((list<string>)
	merge (common_commands, options));
    global_commands = optsort ((list<string>)
	merge (global_commands, common_commands));
    subnet_commands = optsort ((list<string>)
	merge (subnet_commands, common_commands));
    host_commands = optsort ((list<string>)
	merge (host_commands, common_commands));
    shared_net_commands = optsort((list<string>)
	merge (shared_net_commands, common_commands));
    pool_commands = optsort ((list<string>)
	merge (pool_commands, common_commands));
    group_commands = optsort ((list<string>)
	merge (group_commands, common_commands));

    map<string,map<string,any> > w = $[
	"global_table" : getOptionsTableWidget (global_commands),
	"host_table" : getOptionsTableWidget (host_commands),
	"subnet_table" : getOptionsTableWidget (subnet_commands),
	"shared-network_table" : getOptionsTableWidget (shared_net_commands),
	"pool_table" : getOptionsTableWidget (pool_commands),
	"group_table" : getOptionsTableWidget (group_commands),
	"class_table" : getOptionsTableWidget (class_commands),
	"dyn_dns_button" : $[
	    "init" : DynDnsButtonInit,
	    "handle" : DynDnsButtonHandle,
	    "handle_events" : [ "dyn_dns_button" ],
	    "help" : HELPS["dyn_dns_button"]:"",
	    "label" : "&D ",//FIXME CWM should be able to handle virtual widgets
	    "widget" : `textentry,
	],
	"start" : $[
		"widget" : `checkbox,
		// check box
		"label" : _("&Start DHCP Server"),
		"help" : HELPS["start"]:"",
		"init" : startInit,
		"handle" : startHandle,
		"store" : startStore,
		"opt" : [`notify],
	],
	"chroot" : $[
	    "widget" : `checkbox,
	    // check box
	    "label" : _("&Run DHCP Server in Chroot Jail"),
	    "help" : HELPS["chroot"]:"",
	    "init" : chrootInit,
	    "handle" : chrootHandle,
	    "store" : chrootStore,
	],
	"ldap_support" : $[
	    "widget" : `checkbox,
	    // check box
	    "label" : _("LDAP Support"),
	    "help" : HELPS["ldap_support"]:"",
	    "init" : ldapInit,
	    "handle" : ldapHandle,
	    "opt" : [ `notify ],
	],
	"configtree" : $[
		"widget" : `custom,
		"custom_widget" : `VWeight (1, `VBox (
		    `VWeight (1, `ReplacePoint (`id (`configtree_rp), `Tree (
			`id ("configtree"),
			// tree widget
			_("&Configured Declarations"),
			[]
		    ))),
		    `HBox (
			`PushButton (`id (`add), Label::AddButton ()),
			`PushButton (`id (`edit), Label::EditButton ()),
			`PushButton (`id (`delete), Label::DeleteButton ()),
//			`PushButton (`id (`move), _("&Move")),
			`HStretch (),
			// menu button
			`MenuButton (`id (`adv), _("Ad&vanced"), [
			    // item of a menu button
			    `item (`id (`log), _("Display &Log")),
			    // item of a menu button
			    `item (`id (`interfaces), _("&Interface Configuration")),
			    // item of a menu button
			    `item (`id (`tsig_keys), _("TSIG Key Management")),
			])
		    ))),
		"help" : HELPS["configtree"]:"",
		"init" : configTreeInit,
		"handle" : configTreeHandle,
	],
	"subnet" : $[
		"widget" : `custom,
		"custom_widget" : `HBox (
		    `HSpacing (2),
		    // text entry
		    `TextEntry (`id (`subnet), _("&Network Address")),
		    // text entry
		    `TextEntry (`id (`netmask), _("Network &Mask")),
		    `HSpacing (2)
		),
		"help" : HELPS["subnet"]:"",
		"init" : subnetInit,
		"store" : subnetStore,
	    ],
	    "host" : $[
		"widget" : `textentry,
		// text entry
		"label" : Label::HostName (),
		"help" : HELPS["host"]:"",
		"init" : idInit,
		"store" : idStore,
	],
	"group" : $[
		"widget" : `textentry,
		// text entry
		"label" : _("Group &Name"),
		"help" : HELPS["group"]:"",
		"init" : idInit,
		"store" : idStore,
	],
	"pool" : $[
		"widget" : `textentry,
		// text entry
		"label" : _("Pool &Name"),
		"help" : HELPS["pool"]:"",
		"init" : idInit,
		"store" : idStore,
	],
	"shared-network" : $[
		"widget" : `textentry,
		// text entry
		"label" : _("Shared Network &Name"),
		"help" : HELPS["shared-network"]:"",
		"init" : idInit,
		"store" : idStore,
	],
	"class" : $[
		"widget" : `textentry,
		// text entry
		"label" : _("Class &Name"),
		"help" : HELPS["class"]:"",
		"init" : idInit,
		"store" : idStore,
	],
	"interfaces" : $[
	    "widget" : `custom,
	    "custom_widget" : `MultiSelectionBox (
		`id ("interfaces"),
		// multi selection box
		_("Available Interfaces"),
		maplist (string s,
		    filter (
			string s,
			(list<string>)SCR::Dir (.network.section),
			``(s != "lo")
		    ),
		    ``(`item (`id (s), s))
		)
	    ),
	    "help" : HELPS["interfaces"]:"",
	    "init" : interfacesInit,
	    "store" : interfacesStore,
	],
	"open_firewall" : $[
	    "widget" : `checkbox,
	    // check box
	    "label" : _("Open &Firewall for Selected Interface"),
	    "init" : OpenFirewallInit,
	    "store" : OpenFirewallStore,
	    "validate_type" : `function,
	    "validate_function" : OpenFirewallValidate,
	    "help" : HELPS["open_firewall"]:"",
	],
	"ddns_enable" : $[
	    "widget" : `custom,
	    "custom_widget" : `VBox (
		`Left (`CheckBox (`id ("ddns_enable"),
		    `opt (`notify),
		    // check box
		    _("&Enable Dynamic DNS for This Subnet"))),
		`VSpacing (0.5),
		`Left (`ReplacePoint (`id (`ddns_key_rp),
			// combo box
			`ComboBox (`id("ddns_key"), _("Forward Zone TSIG &Key")))),
		`Left (`ReplacePoint (`id (`rev_ddns_key_rp),
                        // combo box
                        `ComboBox (`id("rev_ddns_key"), _("Reverse Zone TSIG &Key")))),
		`Left (`CheckBox (`id (`update_ddns_glob),
		    // check box
		    _("&Update Global Dynamic DNS Settings")))
	    ),
	    // check box
	    "help" : HELPS["enable_ddns"]:"",
	],
	"zone" : $[
	    "widget" : `textentry,
	    // text entry
	    "label" : _("&Zone"),
	    "init" : DDNSZonesInit,
	    "store" : DDNSZonesStore,
	    "handle" : DDNSZonesHandle,
	    "handle_events" : [ "ddns_enable" ],
	    "help" : HELPS["ddns_zones"]:"",
	    "validate_type" : `function,
	    "validate_function" : DNSZonesValidate,
	],
	"zone_ip" : $[
	    "widget" : `textentry,
	    // text entry
	    "label" : _("&Primary DNS Server"),
	    "help" : " ",
//	    "validate_type" : `function,
//	    "validate_function" : EmptyOrIpValidate,
	],
        "reverse_zone": $[
	    "widget" : `textentry,
	    // text entry
	    "label" : _("Re&verse Zone"),
	    "help" : " ",
	],
	"reverse_ip" : $[
	    "widget" : `textentry,
	    // text entry
	    "label" : _("Pr&imary DNS Server"),
	    "help" : " ",
//	    "validate_type" : `function,
//	    "validate_function" : EmptyOrIpValidate,
	],
	"tsig_keys" : CWMTsigKeys::CreateWidget ($[
	    "get_keys_info" : DhcpServer::GetKeysInfo,
	    "set_keys_info" : DhcpServer::SetKeysInfo,
	    "list_used_keys" : DhcpServer::ListUsedKeys,
	]),
	"config_summary" : $[
	    "widget" : `custom,
	    "custom_widget" : `RichText (`id ("config_summary"), ""),
	    "init" : ConfigSummaryInit,
	],
	"all_settings_button" : $[
	    "widget" : `push_button,
	    // push button
	    "label" : _("DHCP Server &Expert Configuration..."),
	    "handle_events" : ["all_settings_button"],
	    "handle" : AllSettingsButtonHandle,
	    "help" : HELPS["all_settings_button"]:"",
	],
    ];
    DhcpServerUI::widgets = w;
}


}
