#!/usr/bin/perl

# isdn_answering

# Copyright (C) 2003 Damien Krotkine (dams@tuxfamily.org)
#
# 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; only version 2, no any other 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.

# DrakX includes
use lib qw(/usr/lib/libDrakX);
use interactive;
use common;
use ugtk2 qw(:helpers :wrappers :create);

# we include the Answering_Machine Glueconf module
use Libconf::Glueconf::Capisuite::AnsweringMachine_conf;
use Libconf::GUI::Gtk2 qw(:generators);

# for debugging purpose
use Data::Dumper;

# make sure the config directory exists
-e '/etc/capisuite/answering_machine.conf' or system('mkdir -p /etc/capisuite/');

# we ask glueconf to give us the structure representing the answering_machine config file
my $struct = new Libconf::Glueconf::Capisuite::AnsweringMachine_conf('/etc/capisuite/answering_machine.conf');

# we dump the content for debugging purpose
print Dumper($struct) . "\n";

# the main window
my $window = Gtk2::Window->new('toplevel');
$window->signal_connect(delete_event => sub { ugtk2->exit(0) });
$window->set_border_width(5);
$window->set_position('center');
$window->set_title(N("ISDN answering machine configuration"));

#we create the list model
my $users_clist_model = Gtk2::ListStore->new('Glib::String');

#we add widget in the main window
gtkadd($window,
       gtkpack_(Gtk2::VBox->new(0,5),
                0, N("ISDN Answering Machine Configurator"),

                #global section
                1, gtkadd(new Gtk2::Frame(N("General parameters")),
                          gtkset_border_width(construct_table($struct,
                              [ N("Audio snippets directory"), '{GLOBAL}{audio_dir}' ],
                              [ N("User-specific data directory"), '{GLOBAL}{voice_user_dir}' ],
                              [ N("Search for audio files"), '{GLOBAL}{user_audio_files}' ],
                              [ N("Voice delay (in sec.)"), '{GLOBAL}{voice_delay}' ],
                              [ N("Announcement"), '{GLOBAL}{announcement}' ],
                              [ N("Record length (in sec.)"), '{GLOBAL}{record_length}' ],
                              [ N("Record silence timeout (in sec.)"), '{GLOBAL}{record_silence_timeout}' ],
                                             ), 5),
                         ),

                #users section
                1, gtkadd(new Gtk2::Frame(N("Users")),
                          gtkset_border_width(gtkpack_(Gtk2::HBox->new(0,5),
                                   1, my $users_clist = Gtk2::TreeView->new_with_model($users_clist_model),
                                   0, gtkadd(gtkset_layout(Gtk2::VButtonBox->new, 'start'),
                                             gtksignal_connect(new Gtk2::Button(N("Add...")), clicked => sub { user_add() }),
                                             gtksignal_connect(new Gtk2::Button(N("Delete")), clicked => sub { user_del() }),
                                             gtksignal_connect(new Gtk2::Button(N("Edit...")), clicked => sub { user_edit() }),
                                            )
                                  ), 5)
                         ),

                #bottom buttons
                0, gtkadd(gtkset_layout(Gtk2::HButtonBox->new, 'end'),
                          gtksignal_connect(new Gtk2::Button(N("Apply")), clicked => sub { save() }),
                          gtksignal_connect(new Gtk2::Button(N("Cancel")), clicked => sub { cancel_exit() }),
                          gtksignal_connect(new Gtk2::Button(N("OK")), clicked => sub { save_exit() }),
                         ),
               )
      );

# we set up the column title of the list
$users_clist->append_column(Gtk2::TreeViewColumn->new_with_attributes(N("Name"), Gtk2::CellRendererText->new, 'text' => 0));

# we fill the list entries
build_user_list();

# we make everything visible in the window
$window->show_all;

#and we start the Gtk2 main loop.
Gtk2->main;

# After the user has clicked on one button, we dump the content of the struct structure for debugging purpose
print Dumper($struct) . "\n";

#and we exit the program.
ugtk2->exit(0);


##### subfonctions #####

# takes the list of label+path in the glueconf struct, and build the gtk table
# correcponding, with the best widget to represent the infos, and a help button
sub construct_table {
    my ($struct) = shift;
    mycreate_packtable({ xpadding => 5,
                         ypadding => 5,
                       },
                       map {
                           my ($label, $path) = @$_;
                           [ $label,
                             getBestWidget($struct, $path),
                             gtksignal_connect(Gtk2::Button->new_from_stock('gtk-help'),
                                               clicked => sub {
                                                   create_dialog(N("Help"),
                                                                 new Gtk2::Label(getDescription($struct, $path)),
                                                                 {
                                                                  stock => 'gtk-dialog-info',
                                                                  cancel => 0,
                                                                 }
                                                                )
                                               }
                                              ),
                           ]
                        } @_
                      )
}

# builds the users list
sub build_user_list() {
    #we clear the list in case it wasn't empty
    $users_clist_model->clear;

    #for each section different from 'GLOBAL', we append a line.
    foreach (keys %$struct) {
        $_ eq 'GLOBAL' and next;
        $users_clist_model->append_set(0 => $_);
    }
}

# called when we want to add a user
sub user_add() {

    # we ask for the name of the new user
    if (create_dialog(N("Enter the name of the user to add"),
                      gtkpack_(gtkset_border_width(Gtk2::HBox->new(0,5), 5),
                               0, N("Name :"),
                               1, my $entry = Gtk2::Entry->new,
                              ),
                      {
                       stock => 'gtk-dialog-info',
                       cancel => 1,
                      }
                     )
       ) {

        my $user = $entry->get_text;
        defined $user && $user ne '' or return;

        # we create a new void structure
        my $user_struct = new Libconf::Glueconf::Capisuite::AnsweringMachine_conf;

        # we give it to edition
        user_edit($user, $user_struct);

        # we rebuild the user list
        build_user_list();
    }
}

# called when we want to edit the user settings
sub user_edit {
    # we may receive a user name and a void user
    my ($user, $user_struct) = @_;

    # if we didn't get a username, we pick the name selected from the gtk list
    if (!defined $user) {
        my @selected = $users_clist->get_selection->get_selected;
        return if !@selected;
        $user = $users_clist_model->get($selected[1], 0);
    }

    # if we didn't get the user struct, we pick it from $struct
    if (!defined $user_struct) {

        # new void struct
        $user_struct = new Libconf::Glueconf::Capisuite::AnsweringMachine_conf();

        # we copy the settings (need work, should be easier than that.
        $user_struct->{$user}{$_} = $struct->{$user}{$_} foreach qw(voice_delay announcement record_length record_silence_timeout voice_numbers pin voice_action);
    }

    # we create the dialog so that it's possible to edit the settings
    if (create_dialog($user,
                      gtkadd(new Gtk2::Frame(N("User parameters")),
                             gtkset_border_width(construct_table($user_struct,
                                 [ N("Voice delay (in sec.)"), "{$user}{voice_delay}" ],
                                 [ N("Announcement"), "{$user}{announcement}" ],
                                 [ N("Record length (in sec.)"), "{$user}{record_length}" ],
                                 [ N("Record silence timeout (in sec.)"), "{$user}{record_silence_timeout}" ],
                                 [ N("Voice numbers"), "{$user}{voice_numbers}" ],
                                 [ N("Pin"), "{$user}{pin}" ],
                                 [ N("Voice action"), "{$user}{voice_action}" ],
                                 ), 5),
                            ),
                      {
                       stock => 'gtk-dialog-info',
                       cancel => 1,
                      }
                     )
       ) {

        # if the changes are validated, we copy the user sttings in $struct.
        $struct->{$user}{$_} = $user_struct->{$user}{$_} foreach qw(voice_delay announcement record_length record_silence_timeout voice_numbers pin voice_action);
    }
}

# called when we want to remove a user
sub user_del() {

    # we get the user name from the selected entry of the list
    my @selected = $users_clist->get_selection->get_selected;

    # if there is nothing selected, we return
    return if !@selected;

    #we actually get the user name
    my $user = $users_clist_model->get($selected[1], 0);

    # we remove the corresponding section of the $struct
    delete $struct->{$user};

    # we rebuild the users list
    build_user_list();
}


# called when the user clicks on the Apply button
sub save() {

    # we ask the $sys_network object to write itself back to the real config file
    # it knows everything about itself, so no need to give him any arg.
    # the file is rewritten, without loosing any information or comments.
    $struct->writeConf;
}

# called when the user clicks on the OK button
sub save_exit() {

    # we save the settings
    save();

    # we exit the gtk2 main loop
    Gtk2->main_quit;
}

# called when the user clicks on the Cancel button
sub cancel_exit() {

    # we exit the gtk2 main loop
    Gtk2->main_quit;
}

# call create_packtable, but ensure labels are right-justified (not very clean)
sub mycreate_packtable {
    my ($options, @l) = @_;
    create_packtable($options, map { [ map { ref $_ ? $_ : gtkpack_(Gtk2::HBox->new(0,0),
                                             1, Gtk2::HBox->new(0,0),
                                             0, Gtk2::Label->new($_)
                                           ) } @$_ ] } @l
                    );
}
