# Copyright 1999-2004, Fred Steinberg, Brown Bear Software

# Admin for specifying which Add-Ins to use, and their colors, etc.
package AdminAddIns;
use strict;

use CGI (qw (:standard *table));
use Calendar::GetHTML;
use Calendar::Javascript;
use Operation::MultiCal;

use vars ('@ISA');
@ISA = ('Operation::MultiCal');

sub perform {
    my $self = shift;

    my ($save, $cancel) = $self->getParams (qw (Save Cancel));

    if ($cancel) {
        my $op = $self->isSystemOp ? 'SysAdminPage' : 'AdminPage';
        print $self->redir ($self->makeURL ({Op => $op}));
        return;
    }

    my $i18n    = $self->I18N;
    my $calName = $self->calendarName;

    my ($calendars, $prefs) = $self->getCalsAndPrefs;

    my $override = 1;
    my $message  = $self->adminChecks;

    if (!$message and $save) {
        $override = 1;
        $self->{audit_formsaved}++;

        my %newInc;
        my @addInNames;

        # Clear checkbox params for every addin, since they won't be
        # seen if not checked.
        # Do FG/BG first, since they are there even if unset
        foreach my $param (keys %{$self->{params}}) {
            next unless ($param =~ /^ADDIN-FG-(.*)/);
            my $name = $1;
            push @addInNames, $name;
            my $dbName = "ADDIN $name";

            my ($fg, $bg, $text) = ($self->{params}->{"ADDIN-FG-$name"},
                                    $self->{params}->{"ADDIN-BG-$name"},
                                    $self->{params}->{"ADDIN-Text-$name"});
            ($newInc{$dbName}{BG} = $bg) =~ s/^\s+//;
             $newInc{$dbName}{BG}        =~ s/\s+$//;
            ($newInc{$dbName}{FG} = $fg) =~ s/^\s+//;
             $newInc{$dbName}{FG}        =~ s/^\s+$//;
            ($newInc{$dbName}{Text} = $text) =~ s/^\s+//;
             $newInc{$dbName}{Text}          =~ s/^\s+$//;
        }

        # Now do the checkboxes
        foreach my $name (@addInNames) {
            my $dbName = "ADDIN $name";
            my $included = $self->{params}->{"ADDIN-Included-$name"};
            my $border   = $self->{params}->{"ADDIN-Border-$name"};
            $newInc{$dbName}{Included} = ($included and
                                          ($included eq 'on')) ? 1 : 0;
            $newInc{$dbName}{Border}   = ($border and
                                          ($border eq 'on'))   ? 1 : 0;
            $newInc{$dbName}{Override} = 1;
        }

        # Remove ignored ones, build confirmation message
        if ($self->isMultiCal) {
            my %map = map {$_ => ["ADDIN $_"]} @addInNames;
            my @modified = $self->removeIgnoredPrefs (map   => \%map,
                                                      prefs => \%newInc);
            $message = $self->getModifyMessage (cals   => $calendars,
                                                mods   => \@modified,
                                                labels => {});
        }

        # Set prefs for each specified calendar
        foreach my $calName (@$calendars) {
            my $thePrefs = Preferences->new ($self->dbByName ($calName));
            my $origInfo = $thePrefs->Includes;

            # remove included AddIns that don't exist anymore
            foreach (keys %$origInfo) {
                next unless /^ADDIN (.*)/;
                delete $origInfo->{$calName} unless (grep /$1/, @addInNames);
            }

            foreach (keys %newInc) {
                $self->{audit_orig}->{$calName}{$_} = $origInfo->{$_};
                $origInfo->{$_} = $newInc{$_};
                # don't bother storing info for ones we don't include
                delete $origInfo->{$_} unless $newInc{$_}{Included};
            }
            $self->dbByName ($calName)->setPreferences ({Includes=>$origInfo});
        }

        $prefs = Preferences->new ($calendars->[0]); # re-get
    }

    my $cgi = new CGI;

    print GetHTML->startHTML (title  => $i18n->get ('Add-Ins'),
                              op     => $self);
    print '<center>';
    if ($self->isSystemOp) {
        print GetHTML->SysAdminHeader ($i18n, 'Add-Ins');
    } else {
        print GetHTML->AdminHeader (I18N    => $i18n,
                                    cal     => $calName || '',
                                    goob    => $self->goobLabel    || '',
                                    group   => $self->groupName    || '',
                                    section => 'Add-Ins');
    }

    print '<br>';
    print "<h3>$message</h3>" if $message;
    print '</center>';

    # (We remove add-ins from the preference list if they no longer
    # exist.)
    print startform;

    # If group, allow selecting any calendar we have Admin permission for
    my %onChange = ();
    if ($self->isMultiCal) {
        my ($calSelector, $message) = $self->calendarSelector;
        print $message if $message;
        print $calSelector if $calSelector;
    }

    my $helpString = $i18n->get ('AdminAddIns_HelpString');
    if ($helpString eq 'AdminAddIns_HelpString') {
        my $sysString = $self->isSystemOp ? ' by default for new calendars'
                                          : '';
        ($helpString =<<"        FNORD") =~ s/^ +//gm;
            Select which Add-Ins you would like to include$sysString. You can
            specify the colors to use for each event from an Add-In, and
            whether or not to draw a border. If you leave a color blank, the
            default color for the calendar will be used.<br>
        FNORD
    }
    print $helpString;

    my %addInsDB;

    my $masterDB = MasterDB->new;
    foreach (AddIn->getAddInFilenames ($masterDB)) {
        $addInsDB{$_} = $masterDB;
    }
    if ($calName) {
        foreach (AddIn->getAddInFilenames ($self->db)) {
            $addInsDB{$_} = $self->db;
        }
    }
    my @allAddIns  = keys %addInsDB; # cal specific overwrite system ones
    my $includes   = $prefs->Includes;

    my ($thisRow, $thatRow) = ('thisRow', 'thatRow');

    my @tableRows;
    foreach my $name (sort {lc($a) cmp lc($b)} @allAddIns) {

        my $db = AddIn->new ($name, $addInsDB{$name});
        my $dbName = "ADDIN $name";

        my ($includeCB, $fgField, $bgField, $textField, $borderCB, $border,
            $fgColor, $bgColor, $incP, $text);
        if (defined $includes->{"$dbName"}) {
            $incP     = $includes->{$dbName}{'Included'};
            $border   = $includes->{$dbName}{'Border'};
            $fgColor  = $includes->{$dbName}{'FG'}   || '';
            $bgColor  = $includes->{$dbName}{'BG'}   || '';
            $text     = $includes->{$dbName}{'Text'} || '';
        } else {
            $incP = $border = $fgColor = $bgColor = $text = '';
        }

        my $onChange;
        $onChange = $self->getOnChange ($name)
            if ($self->isMultiCal);


        $includeCB  = checkbox (-name    => "ADDIN-Included-$name",
                                -checked => $incP,
                                -override => $override,
                                -onChange => $onChange,
                                -label   => " $name");
        $borderCB   = checkbox (-name    => "ADDIN-Border-$name",
                                -checked => $border,
                                -override => $override,
                                -onChange => $onChange,
                                -label   => '');
        $fgField = textfield (-name      => "ADDIN-FG-$name",
                              -default   => $fgColor,
                              -override  => $override,
                              -onChange  => $onChange,
                              -size      => 10,
                              -maxlength => 20);
        $bgField = textfield (-name      => "ADDIN-BG-$name",
                              -default   => $bgColor,
                              -override  => $override,
                              -onChange  => $onChange,
                              -size      => 10,
                              -maxlength => 20);
        $textField = textfield (-name      => "ADDIN-Text-$name",
                                -default   => $text,
                                -override  => $override,
                                -onChange  => $onChange,
                                -size      => 10,
                                -maxlength => 2000);

        ($thisRow, $thatRow) = ($thatRow, $thisRow);

        push @tableRows, Tr ({-class => $thisRow},
                             $self->groupToggle (name  => $name),
                             td ($includeCB),
                             td ({-bgcolor => $bgColor},
                                 qq (<span style="color: $fgColor;">) .
                                 $db->description . '</span>'),
                             td ({align => 'center'},
                                 [$fgField, $bgField, $borderCB, $textField]));
    }

    if (@tableRows) {

        print q {
             <SCRIPT LANGUAGE="JavaScript">
             <!--
             function SetAll (setThem) {
                 theform=document.forms[0];
                 for (i=0; i<theform.elements.length; i++) {
                     if (theform.elements[i].type =='checkbox' &&
                         theform.elements[i].name.match ('ADDIN-Included-')) {
                         theform.elements[i].checked = setThem;
                     }
                 }
             }
             //-->
             </SCRIPT>
            };

        my $groupSetAll = '';
        my $togHead = '';
        if ($self->isMultiCal) {
            my ($js, $setAllRow) = $self->setAllJavascript;
            print $js;
            $groupSetAll = $cgi->td ({-align => 'center'}, $setAllRow)
                if $setAllRow;
            $togHead = th ('&nbsp;');
        }

        print table ({class        => 'alternatingTable',
                      border       => 0,
                      cellspaceing => 0,
                      cellpadding  => 2},
                     $togHead,
                     th ({-align => 'left', -class => 'caption'},
                         [$i18n->get ('Include?'),
                          $i18n->get ('Description')]),
                     th ({-align => 'center', -class => 'caption'},
                         [$i18n->get ('Foreground Color'),
                          $i18n->get ('Background Color'),
                          $i18n->get ('Border'),
                          $i18n->get ('Identifying Text')]),
                     @tableRows,
                     Tr ($groupSetAll,
                         $cgi->td ($cgi->a ({-href =>
                                             "javascript:SetAll(true)"},
                                            '<small>Select All</small>') .
                                   '&nbsp;' .
                                   $cgi->a ({-href =>
                                             "javascript:SetAll(false)"},
                                            '<small>Clear All</small>'))));
    } else {
        print $cgi->center ($cgi->b ($i18n->get ('There are no Add-Ins ' .
                                                 'available to include.')));
    }

    print '<br>';
    print Javascript->ColorPalette ($self);
    print a ({-href   => "Javascript:ColorWindow()"},
             $i18n->get ('See Available Colors'));
    print '<br><hr>';

    print submit (-name => 'Save',   -value => $i18n->get ('Save'));
    print '&nbsp;';
    print submit (-name => 'Cancel', -value => $i18n->get ('Done'));
    print '&nbsp;';
    print reset  (-value => 'Reset');

    print $self->hiddenParams;

    print endform;
    print $self->helpNotes;
    print end_html;
}

sub cssDefaults {
    my $self = shift;
    my $css = $self->SUPER::cssDefaults;
    $css .= GetHTML->AdminCSS ($self);
    return $css;
}

sub auditString {
    my ($self, $short) = @_;
    return unless $self->{audit_formsaved};
    my $line = $self->basicAuditString ($short);

    my $cal = $self->currentCal;

    my $orig = $self->{audit_orig}->{$cal};
    my $new  = Preferences->new ($cal)->Includes;

    my $info;
    foreach my $cal (sort keys %$orig) {
        my $diffs;
        foreach (sort keys %{$orig->{$cal}}) {
            next if ($_ eq 'Categories');
            my $old = $orig->{$cal}->{$_} || "''";
            my $gnu = $new->{$cal}->{$_}  || "''";
            next if ($old eq $gnu);
            $diffs .= " ($_: $old -> $gnu)";
        }
        $cal =~ /ADDIN (.*)/;
        if ($diffs) {
            $info .= "\n" unless $short;
            $info .= " [$1 -$diffs]";
        }
    }
    return unless $info;     # don't report if nothing changed
    return $line . $info;
}

1;
