/
CDC-1.1/
parent $misc
object $has_settings

var $root dbref 'has_settings
var $root child_index 0
var $root fertile 1
var $root manager $has_settings
var $root owned [$has_settings]
var $root owners [$has_settings]
var $root writable []
var $root readable ['parameters, 'methods, 'code]
var $root inited 1
var $has_settings settings #[]
var $has_settings setting_templates #[]

method setting_templates
    (> .perms(sender()) <);
    return setting_templates || #[];
.

method all_setting_templates
    var obj, tmpl, out;
    
    (> .perms(sender()) <);
    out = #[];
    for obj in (.ancestors()) {
        tmpl = (| obj.setting_templates() |);
        if (tmpl)
            out = dict_add(out, obj, tmpl);
        if (obj == definer())
            break;
    }
    return out;
.

method add_setting_template
    arg template, type;
    
    (> .perms(sender()) <);
    if (!setting_templates)
        setting_templates = #[];
    if (type(template) != 'string)
        throw(~type, "Setting templates must be strings.");
    if (type(type) != 'symbol)
        throw(~type, "Setting data types must be symbols.");
    setting_templates = dict_add(setting_templates, template, type);
.

method del_setting_template
    arg template;
    
    (> .perms(sender()) <);
    if (setting_templates) {
        if (template in dict_keys(setting_templates))
            setting_templates = dict_del(setting_templates, template);
    }
.

method set_setting
    arg flag, value;
    var template, objects, x, y, type;
    
    (> .perms(sender()) <);
    
    // is it a valid template?
    template = (| .setting_template(flag) |);
    if (!template)
        throw(~setting, ("Unknown setting \"" + flag) + "\".");
    
    // make sure the value is submitted correctly.
    type = template[2];
    switch (type) {
        case 'boolean:
            if (!(value in [1, 0]))
                throw(~type, ("Value must be boolean (+/-" + flag) + ").");
        case 'integer:
            if (type(value) != 'integer)
                throw(~type, ("Value must be an integer (" + flag) + "=<integer>).");
        case 'string:
            if (type(value) != 'string)
                throw(~type, ("Value must be a string (" + flag) + "=<string>).");
        default:
            throw(~type, "Setting has an unknown type definition, IT'S BROKE.");
    }
    
    // incase they weren't initialized, initialize settings.
    if (!settings)
        settings = #[];
    
    // Ok, set it...
    // for space concerns, if value is null remove the setting.
    if (((type == 'boolean) && (value == 0)) || ((type == 'string) && (value == ""))) {
        if ((| settings[template[1]] |))
            return .unset_setting(template[1]);
    }
    settings = dict_add(settings, template[1], [type, value]);
.

method unset_setting
    arg template;
    
    (> .perms(sender()) <);
    if ((| settings[template] |))
        settings = dict_del(settings, template);
.

method settings
    (> .perms(sender()) <);
    return settings || #[];
.

method setting
    arg template;
    
    return (| (settings[template])[2] |) || 0;
.

method setting_template
    arg template;
    var templates, t, obj;
    
    (> .perms(sender()) <);
    for obj in (.ancestors()) {
        templates = (| obj.setting_templates() |);
        if (templates) {
            t = (| templates[template] |);
            if (t)
                return [template, t];
        }
        if (obj == definer())
            break;
    }
    return 0;
.