#!/usr/bin/perl -w

use strict;

# mangling to names:
#   bool: enable-$/disable-$, int,string: set-$

# setting name	-> [ '/path/to/key',
#                    'bool|string|int|custom',
#                    '<help-description>',
#                    &custom_func ]
my $path_idx = 0;
my $type_idx = 1;
my $help_idx = 2;
my $func_idx = 3;

my $settings = {
    'enable-auto-save'     => [ '/apps/openoffice/auto_save', 'bool', 'Save AutoRecovery information' ],
    'enable-create-backup' => [ '/apps/openoffice/create_backup', 'bool', 'Always create backup copy' ],
    'enable-font-anti-aliasing' => [ '/apps/openoffice/use_font_anti_aliasing', 'bool', 'Screen font antialiasing' ],
    'enable-font-history' => [ '/apps/openoffice/show_font_history', 'bool', 'Show font history' ],
    'enable-font-preview' => [ '/apps/openoffice/show_font_preview', 'bool', 'Show preview of fonts' ],
    'enable-menu-icons' => [ '/apps/openoffice/show_menu_icons', 'bool', 'Show icons in menus' ],
    'enable-menu-inactive-items' => [ '/apps/openoffice/show_menu_inactive_items', 'bool', 'Show inactive menu items' ],
    'enable-opengl' => [ '/apps/openoffice/use_opengl', 'bool', 'Use OpenGL' ],
    'enable-optimize-opengl' => [ '/apps/openoffice/optimize_opengl', 'bool', 'Optimized output for OpenGL' ],
    'enable-printing' => [ '/desktop/gnome/lockdown/disable_printing', 'custom:bool', 'Allow printing', \&inverted_boolean ],
    'enable-printing-modifies-doc' => [ '/apps/openoffice/printing_modifies_doc', 'bool', 'Printing sets document-modified status' ],
    'enable-recommend-password-on-save' => [ '/apps/openoffice/lockdown/recommend_password_on_save', 'bool', 'Recommend password protection on saving' ],
    'enable-remove-personal-info-on-save' => [ '/apps/openoffice/lockdown/remove_personal_info_on_save', 'bool', 'Remove personal information on saving' ],
    'enable-system-file-dialog' => [  '/apps/openoffice/use_system_file_dialog', 'bool', 'Use system file dialogs' ],
    'enable-system-font' => [  '/apps/openoffice/use_system_font', 'bool', 'Use system font for user interface' ],
    'enable-ui-customization' => [ '/apps/openoffice/lockdown/disable_ui_customization', 'custom:bool', 'Allow UI customization', \&inverted_boolean ],
    'enable-warn-alien-format' => [ '/apps/openoffice/warn_alien_format', 'bool', 'Warn when not saving in OpenDocument or default format' ],
    'enable-warn-info-create-pdf' => [ '/apps/openoffice/lockdown/warn_info_create_pdf', 'bool', 'Warn if document contains information on creating pdf' ],
    'enable-warn-info-printing' => [ '/apps/openoffice/lockdown/warn_info_printing', 'bool', 'Warn if document contains information on printing' ],
    'enable-warn-info-signing' => [ '/apps/openoffice/lockdown/warn_info_signing', 'bool', 'Warn if document contains information on signing' ],
    'enable-warn-info-saving' => [ '/apps/openoffice/lockdown/warn_info_saving', 'bool', 'Warn if document contains information on saving' ],
    'set-auto-save-interval' => [ '/apps/openoffice/auto_save_interval', 'int', 'Minutes to save AutoRecovery information' ],
    'set-defaults' => [ 'dummy for help', 'dummy for help', 'Revert to default settings' ],
    'set-font-anti-aliasing-min-pixel' => [  '/apps/openoffice/font_anti_aliasing_min_pixel', 'int', 'Pixels to use screen font antialiasing from' ],
    'set-icon-size' => [ '/apps/openoffice/icon_size', 'custom:int', 'Icon size', \&parse_icon_size ],
    'set-macro-security-level' => [ '/apps/openoffice/lockdown/macro_security_level', 'custom:int', 'Macro security level', \&parse_macro_security_level ],
    'set-undo-steps' => [ '/apps/openoffice/undo_steps', 'int', 'Number of Undo steps' ],
    'set-writer-default-document' => [ '/apps/openoffice/writer_default_document_format', 'custom:string', 'Default Writer file format', \&parse_writer ],
    'set-calc-default-document' => [ '/apps/openoffice/calc_default_document_format', 'custom:string', 'Default Calc file format', \&parse_calc ],
    'set-impress-default-document' => [ '/apps/openoffice/impress_default_document_format', 'custom:string', 'Default Impress file format', \&parse_impress ]
};

sub inverted_boolean($$$)
{
    my ($attrs, $key, $value) = @_;
    return '0' if ($value eq 'yes');
    return '1' if ($value eq 'no');
    die "Error: supported values of $key are yes|no: $value is invalid\n";
}

sub validate_enum($$$)
{
    my ($opts, $value, $key) = @_;

    my @enum_opts = split (/,/, $opts);
    my $hit = 0;
    for my $val (@enum_opts) {
	$hit = 1 if ($val eq $value);
    }
    if (!$hit) {
	print STDERR "Error: supported values of $key are $opts: $value is invalid\n";
	exit 1;
    }
}

sub parse_icon_size($$$)
{
    my ($attrs, $key, $value) = @_;
    validate_enum ("small,large,auto", $value, $key);
    return '0' if ($value eq 'small');
    return '1' if ($value eq 'large');
    return '2' if ($value eq 'auto');
    die "impossible";
}

sub parse_macro_security_level($$$)
{
    my ($attrs, $key, $value) = @_;
    validate_enum ("low,medium,high,veryhigh", $value, $key);
    return '0' if ($value eq 'low');
    return '1' if ($value eq 'medium');
    return '2' if ($value eq 'high');
    return '3' if ($value eq 'veryhigh');
    die "impossible";
}

sub parse_writer($$$)
{
    my ($attrs, $key, $value) = @_;
    validate_enum ("odt,doc,sxw", $value, $key);
    return "writer8" if ($value eq 'odt');
    return "MS Word 97" if ($value eq 'doc');
    return "StarOffice XML (Writer)" if ($value eq 'sxw');
    die "impossible";
}

sub parse_calc($$$)
{
    my ($attrs, $key, $value) = @_;
    validate_enum ("ods,xls,sxc", $value, $key);
    return "calc8" if ($value eq 'ods');
    return "MS Excel 97" if ($value eq 'xls');
    return "StarOffice XML (Calc)" if ($value eq 'sxc');
    die "impossible";
}

sub parse_impress($$$)
{
    my ($attrs, $key, $value) = @_;
    validate_enum ("odp,ppt,sxi", $value, $key);
    return "impress8" if ($value eq 'odp');
    return "MS PowerPoint 97" if ($value eq 'ppt');
    return "StarOffice XML (Impress)" if ($value eq 'sxi');
    die "impossible";
}

sub help()
{
    print "Usage: ooconfig --setting=value\n  where setting is one of:\n";
    for my $key (keys %{$settings}) {
	my $attrs = $settings->{$key};
	my $help = $attrs->[$help_idx];
	print "\t--" . $key;
	print " : $help" if (defined $help);
	print "\n";
    }
}

sub set_defaults()
{
    my $sys_str = "gconftool-2 --recursive-unset '/apps/openoffice'";
    `$sys_str` && die "Unset failed: $!";
    $sys_str = "gconftool-2 --set '/desktop/gnome/lockdown/disable_printing' --type bool '0'";
    `$sys_str` && die "Reset failed: $!";
}

sub conf_type($)
{
    my $type = shift;
    $type = (split(/:/, $type))[1] if ($type  =~ m/^custom:(.*)$/);
    return $type;
}

sub set_key($$)
{
    my ($attrs, $conf_value) = @_;
    my $sys_str = "gconftool-2 " .
	"--set '" . $attrs->[$path_idx] . "' " .
	"--type " . conf_type ($attrs->[$type_idx]) . " " .
	"'" . $conf_value . "'";
#    print "\$ $sys_str\n";
    `$sys_str` && die "Set failed: $!";
}

for my $arg (@ARGV) {
    if ($arg =~ m/^--help/ || $arg =~ m/^-h/) {
	help();
	exit 0;
    }
    if ($arg eq '--set-defaults') {
	set_defaults();
	exit 0;
    }
    if (!($arg =~ m/^--(.*)=(.*)/)) {
	print STDERR "Error: syntax --enable-foo=yes\n";
	exit 1;
    }
    if (!defined $settings->{$1}) {
	print STDERR "Unknown setting '$arg'\n";
	exit 1;
    }
}

for my $arg (@ARGV) {
    $arg =~ m/^--(.*)=(.*)/;
    my $key = $1;
    my $value = $2;
    my $attrs = $settings->{$key};
    my $path  = $attrs->[$path_idx];
    my $type  = $attrs->[$type_idx];

#    print "Key '$key' value '$value' '$arg' $attrs, $path, $type\n";
    my $conf_value;

    if ($type eq 'bool') {
	if ($value =~ m/^yes$/g ||
	    $value =~ m/^true$/g) {
	    $conf_value = 1;
	} elsif ($value =~ m/^no$/g ||
	         $value =~ m/^false$/g) {
	    $conf_value = 0;
	} else {
	print STDERR "Error: supported values of $key are yes|no: $value is invalid\n";
	exit 1;
	}

    } elsif ($type eq 'int' ||
	     $type eq 'string') {
	$conf_value = $value;

    } elsif ($type =~ m/^custom:(.*)$/) {
	my $function = $attrs->[$func_idx];
	$conf_value = $function->($attrs, $key, $value);

    } else {
	print STDERR "Error in type '$type' on key '$key'\n";
	exit 1;
    }
    set_key ($attrs, $conf_value);
}
