#!/usr/bin/perl
#*****************************************************************************
#
#  dragoraUpdate
#  Copyright (c) 2014-2017 Angelo Naselli <anaselli@linux.it>
#
#  MandrivaUpdate and MageiaUpdate
#  Copyright (c) 2002 Guillaume Cottenceau
#  Copyright (c) 2002-2014 Thierry Vignaud <tvignaud@mandriva.com>
#  Copyright (c) 2003, 2004, 2005 MandrakeSoft SA
#  Copyright (c) 2005-2007 Mandriva SA
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License version 2, as
#  published by the Free Software Foundation.
#
#  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.
#
#*****************************************************************************
#

use strict;
use English;
use MDK::Common::Func 'any';
use File::ShareDir ':ALL';

use ManaTools::Rpmdragora::init;

use ManaTools::rpmdragora;
use ManaTools::Rpmdragora::gui;
use ManaTools::Rpmdragora::rpmnew;
use ManaTools::Rpmdragora::formatting;
use ManaTools::Rpmdragora::pkg;
use ManaTools::Shared::Locales;
use ManaTools::Shared::GUI;

use yui;


# make Rpmdrake::gui aware MageiaUpdate do not use the same columns ids as rpmdrake:
%pkg_columns = (
    image => 0,
    selected => 1,
    text => 2,
    short_name => 3,
    version => 4,
    release => 5,
    'arch' => 6,
    importance => 7,
);


our $w;
# TODO try to see if we can Moosify all!
our $statusbar;
my $loc = ManaTools::rpmdragora::locale();

if ($EUID != 0) {
    ManaTools::rpmdragora::interactive_msg(
         $loc->N("rpmdragora update"),
         $loc->N("root privileges required, or run <%s> instead", "mana update")
   );
   exit 0 ;
}


my (%data, $initialized);

my %update_icons = (
    security => { icon => 'images/rpmdragora/security-update.png', text => $loc->N("Security") },
    bugfix   => { icon => 'images/rpmdragora/bugfix-update.png',   text => $loc->N("Bug fixing") },
    normal   => { icon => 'images/rpmdragora/general-update.png',  text => '' },
    title    => { icon => 'images/rpmdragora/title-update.png',    text => $loc->N("Here is the list of software package updates") },
);

my %icons_cache;


sub _refresh_packages_list {
    my ($dialog, $packageTbl) = @_;

    my $item = $packageTbl->selectedItem();
    my $packageName = $item ? $data{$item->index()}{name} : undef;

    # select packages to update:
    my @requested = sort grep { $pkgs->{$_}{pkg} } @filtered_pkgs;

    # don't select packages in skip list:
    if (!$initialized) {
        undef $pkgs->{$_}{selected} foreach @requested;
        my @selectable = grep { !$pkgs->{$_}{pkg}->flag_skip } @requested;
        toggle($packageTbl, @selectable) if @selectable;
        $initialized = 1;
    }

    $dialog->startMultipleChanges();
    $packageTbl->deleteAllItems();

    if (scalar(@requested)) {
        my $itemCollection = new yui::YItemCollection;
        my $i = 0;
        foreach (@requested) {
            my $summary = get_summary($_);
            my ($name, $version, $release, $arch) = split_fullname($_);
            # TODO check if %data is needed
            $data{$i} = { name => $name, fullname => $_ }; $i++;
            my $pkg = $pkgs->{$_};
            my $raw_medium = pkg2medium($pkg->{pkg}, $urpm);
            my $medium = !$raw_medium->{fake} ? $raw_medium->{name} : undef;
            my $icon = "";

            $item = new yui::YCBTableItem("", $name , $summary, $version, $release, $arch);

            my $importance = $medium && $descriptions->{$medium}{$name}{importance};
            if ($importance) {
                my $update_label = "";
                if (yui::YUI::app()->hasImageSupport()) {
                    $icon = File::ShareDir::dist_file(ManaTools::Shared::distName(), $update_icons{$importance}->{icon});
                }
                else {
                    # For ncurses set a label
                    $update_label = $update_icons{$importance}->{name};
                }
                my $cell = new yui::YTableCell($item, 1, $update_label, $icon);
            }

            $item->check($pkgs->{$_}{selected});
            $item->setLabel($name);
            $item->setSelected(1) if ($packageName && $name eq $packageName);
            $itemCollection->push($item);
            $item->DISOWN();
        }
        $packageTbl->addItems($itemCollection);

    }
    $dialog->doneMultipleChanges();

    # return number of packages to be updated
    return scalar(@requested);
}

#=============================================================

=head2 toggle

=head3 INPUT

    $packageTbl: CBYTable containing all the packages to be updated
    @names:      list of package names to be toggled

=head3 DESCRIPTION

    This function toggle a package status from "to be installed" to "to be updated" and viceversa
    based on the first package status.

=cut

#=============================================================
sub toggle {
    my ($packageTbl, @names) = @_;
    my $name = $names[0];
    # TODO working with a single package instead a list...
    #      since it's used only in that case
    my $val = $pkgs->{$name}{selected};
    my $old_status = $val ? 'to_install' : 'to_update';
    my $done;
    my $pkg = $pkgs->{$name}{pkg};
    return if !$pkg;
    $pkg->set_flag_skip(0);

    toggle_nodes($packageTbl, $packageTbl, sub {}, $old_status, @names);
}

#=============================================================

=head2 toggle_all_packages

=head3 INPUT

    $packageTbl: CBYTable containing all the packages to be updated
    $val:        new value wanted for the status (1 selected)

=head3 DESCRIPTION

    This function select or deselect all the packages according to
    the $val passed.

=cut

#=============================================================
sub toggle_all_packages {
    my ($packageTbl, $val) = @_;
    my $it;
    my @l;
    my $i=0;
    # using iterators
    for ($it = $packageTbl->itemsBegin(); $it != $packageTbl->itemsEnd(); ) {
       my $item  = $packageTbl->YItemIteratorToYItem($it);
       my $cbItem = $packageTbl->toCBYTableItem($item);

       push @l, $data{$item->index()}{fullname} if $cbItem->checked() != $val;

       $it = $packageTbl->nextItem($it);
       $i++;
       if ($i == $packageTbl->itemsCount()) {
            last;
       }
    }

    #revert old status
    my $old_status = $val ? 'to_update' : 'to_install';

    toggle_nodes($packageTbl, $packageTbl, sub {}, $old_status, @l);
}

sub quit() {
#     ($mandrivaupdate_width->[0], $mandrivaupdate_height->[0]) = $::w->{real_window}->get_size;
    real_quit();
}

sub run_treeview_dialog {
    my ($callback_action) = @_;

    my ($list, $info, $update_button);

    my $appTitle = yui::YUI::app()->applicationTitle();

    ## set new title to get it in dialog
    yui::YUI::app()->setApplicationTitle($loc->N("Software Management"));
    ## set icon
    my $icon = File::ShareDir::dist_file(ManaTools::Shared::distName(), 'images/rpmdragora/dragoraUpdate.png');
    yui::YUI::app()->setApplicationIcon($icon);

    my $mageiaPlugin = "mga";
    my $factory      = yui::YUI::widgetFactory;
    my $mgaFactory   = yui::YExternalWidgets::externalWidgetFactory($mageiaPlugin);
    $mgaFactory      = yui::YMGAWidgetFactory::getYMGAWidgetFactory($mgaFactory);

    my $dialog  = $factory->createMainDialog;

    $::main_window = $dialog; # rpmdrake way of working :(

    my $vbox    = $factory->createVBox( $dialog );

    #Line for logo and title
    my $hbox_iconbar  = $factory->createHBox($vbox);
    my $head_align_left  = $factory->createLeft($hbox_iconbar);
    $hbox_iconbar     = $factory->createHBox($head_align_left);
    my $wm_icon = File::ShareDir::dist_file(ManaTools::Shared::distName(), $update_icons{'title'}->{icon});
    $factory->createImage($hbox_iconbar, $wm_icon);

    $factory->createHeading($hbox_iconbar, $update_icons{'title'}->{text});


    my $yTableHeader = new yui::YTableHeader();
    # checkbox
    $yTableHeader->addColumn("", $yui::YAlignCenter);
    # icon
    $yTableHeader->addColumn("", $yui::YAlignCenter);
    $yTableHeader->addColumn($loc->N("Name"), $yui::YAlignBegin);
    $yTableHeader->addColumn($loc->N("Summary"), $yui::YAlignBegin);
    $yTableHeader->addColumn($loc->N("Version"),  $yui::YAlignCenter);
    $yTableHeader->addColumn($loc->N("Release"), $yui::YAlignBegin);
    $yTableHeader->addColumn($loc->N("Arch"), $yui::YAlignBegin);

    ## service list (serviceBox)
    my $packageTbl = $mgaFactory->createCBTable($vbox, $yTableHeader, $yui::YCBTableCheckBoxOnFirstColumn);
                     $factory->createVSpacing($vbox, 1);
    my $infoBox    = $factory->createRichText($vbox, "", 0);

    # dialog buttons
    $factory->createVSpacing($vbox, 1.0);
    ## Window push buttons
    my $hbox  = $factory->createHBox( $vbox );
    $hbox->setWeight(0, 1);
    my $align = $factory->createLeft($hbox);
    $hbox     = $factory->createHBox($align);

    my $helpButton  = $factory->createPushButton($hbox, $loc->N("&Help"));
    my $aboutButton = $factory->createPushButton($hbox, $loc->N("&About") );
    $align = $factory->createRight($hbox);
    $hbox  = $factory->createHBox($align);

    ### Service Refresh button ($refreshButton)
    my $uncheckButton = $factory->createPushButton($hbox, $loc->N("U&ncheck all"));
    my $selectButton  = $factory->createPushButton($hbox, $loc->N("&Select all"));
    my $updateButton  = $factory->createPushButton($hbox, $loc->N("&Update"));
    my $closeButton   = $factory->createPushButton($hbox, $loc->N("&Quit") );
    $statusbar        = $factory->createBusyIndicator($vbox, "" );
    $statusbar->setWeight(0, 1);

    $ManaTools::Rpmdragora::pkg::probe_only_for_updates = 1; # faster startup

    pkgs_provider('all_updates', pure_updates => 1); # default mode

    my $num_pkgs = _refresh_packages_list($dialog, $packageTbl);
    if ($num_pkgs) {

        $packageTbl->setImmediateMode(1);
        $packageTbl->setWeight(0, 50);
        my $item = $packageTbl->selectedItem();
        if ($item) {
            my $pkg = $data{$item->index()}{fullname};
            ManaTools::Rpmdragora::gui::setInfoOnWidget($pkg, $infoBox);
        }

        my $info_options = {};

        while(1) {
            my $event     = $dialog->waitForEvent();
            my $eventType = $event->eventType();

            #event type checking
            if ($eventType == $yui::YEvent::CancelEvent) {
                last if quit();
            }
            elsif ($eventType == $yui::YEvent::MenuEvent) {
                my $item = $event->item();
                if (!$item) {
                    #URL emitted or at least a ref into RichText widget
                    my $url = yui::toYMenuEvent($event)->id ();
                    if (ManaTools::Rpmdragora::gui::info_details($url, $info_options) )  {
                        $item = $packageTbl->selectedItem();
                        my $pkg = $data{$item->index()}{fullname};
                        ManaTools::Rpmdragora::gui::setInfoOnWidget($pkg, $infoBox, $info_options);
                    }
                    else {
                        # default it's really a URL
                        ManaTools::Rpmdragora::gui::run_browser($url);
                    }
                }
            }
            elsif ($eventType == $yui::YEvent::WidgetEvent) {
                # widget selected
                my $widget = $event->widget();

                if ($widget == $closeButton) {
                    last if quit();
                }
                elsif ($widget == $aboutButton) {
                    my $translators = ManaTools::Shared::i18NTranslators($loc->N("_: Translator(s) name(s) & email(s)\n"));

                    my $sh_gui = ManaTools::Shared::GUI->new();
                    $sh_gui->AboutDialog({
                        name    => "dragoraUpdate",
                        version => $VERSION,
                        credits => $loc->N("Copyright (C) %s Mageia community", '2013-2017'),
                        license => $loc->N("GPLv2"),
                        description => $loc->N("dragoraUpdate is the Mageia package management tool."),
                        authors => $loc->N("<h3>Developers</h3>
                                            <ul><li>%s</li></ul>
                                            <h3>Translators</h3>
                                            <ul>%s</ul>",
                                            "Angelo Naselli &lt;anaselli\@linux.it&gt;",
                                            $translators
                        ),
                    });
                }
                elsif ($widget == $packageTbl) {
                    yui::YUI::app()->busyCursor();
                    my $item = $packageTbl->selectedItem();
                    if ($item) {
                        my $pkg = $data{$item->index()}{fullname};
                        $info_options = {};
                        ManaTools::Rpmdragora::gui::setInfoOnWidget($pkg, $infoBox);
                    }
                    my $wEvent = yui::toYWidgetEvent($event);
                    if ($wEvent->reason() == $yui::YEvent::ValueChanged) {
                        $item = $packageTbl->changedItem();
                        if ($item) {
                            my $name = $data{$item->index()}{fullname};
                            toggle($packageTbl, $name );
                            $num_pkgs = _refresh_packages_list($dialog, $packageTbl);
                        }
                    }
                    yui::YUI::app()->normalCursor();
                }
                elsif ($widget == $selectButton) {
                    yui::YUI::app()->busyCursor();
                    toggle_all_packages($packageTbl, 1);
                    $num_pkgs = _refresh_packages_list($dialog, $packageTbl);

                    yui::YUI::app()->normalCursor();
                }
                elsif ($widget == $uncheckButton) {
                    yui::YUI::app()->busyCursor();
                    toggle_all_packages($packageTbl, 0);
                    $num_pkgs = _refresh_packages_list($dialog, $packageTbl);
                    yui::YUI::app()->normalCursor()
                }
                elsif ($widget == $updateButton) {
                    my $res = do_action({ tree_mode => 'all_updates' }, $callback_action);
                    $initialized = 0 if !$res;
                    $num_pkgs =  _refresh_packages_list($dialog, $packageTbl);
                    $infoBox->setValue("");
                    if ($num_pkgs) {
                        $item = $packageTbl->selectedItem();
                        if ($item) {
                            my $pkg = $data{$item->index()}{fullname};
                            ManaTools::Rpmdragora::gui::setInfoOnWidget($pkg, $infoBox);
                        }
                    }
                }
                elsif ($widget == $helpButton) {
                }
                last if !$num_pkgs;
            }
        }
    }

    if (!$num_pkgs) {
        ManaTools::rpmdragora::interactive_msg(
            $loc->N("rpmdragora update"),
            $loc->N("The list of updates is empty. This means that either there is no available update for the packages installed on your computer, or you already installed all of them."),
            scroll => 1,
           # main_dialog => 1,
        );
    }

    $dialog->destroy();

    #restore old application title
    yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle;

}
# -=-=-=---=-=-=---=-=-=-- main -=-=-=---=-=-=---=-=-=-

ManaTools::Rpmdragora::rpmnew::do_merge_if_needed();

ManaTools::rpmdragora::readconf();

init();
run_treeview_dialog(\&perform_installation);

ManaTools::rpmdragora::writeconf();

# myexit(0);
