# Arch Perl library, Copyright (C) 2004 Mikhael Goikhman, Enno Cramer
#
# 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; either version 2 of the License, or
# (at your option) any later 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

use 5.006;
use strict;
use warnings;

package ArchWay::Widget::ArchiveRegistry::Lists;

use Glib qw(TRUE FALSE);
use Gtk2;

use base qw(Gtk2::Notebook);

use ArchWay::Widget::FrameScroll;

use constant PAGE_LABELS => ('Registered', 'Mirrored on sourcecontrol.net', 'Search results');
use constant COLUMN_LABELS => qw(Archive Location);

use constant PAGE_REGIST => 0;
use constant PAGE_MIRROR => 1;
use constant PAGE_SEARCH => 2;

sub new ($$$) {
	my $class = shift;
	my $window = shift || die "No window given";
	my $registry = shift || die "No registry given";

	my $self = bless Gtk2::Notebook->new, $class;

	$self->{window} = $window;
	$self->{registry} = $registry;
	$self->{mirror_queried} = 0;
	$self->{mirror_status} = "Click on the empty list area to query supermirror";
	$self->{search_status} = "No search was performed yet";
	$self->_init;

	$self->signal_connect(switch_page => sub {
		$self->update_status($_[2]);
	});

	return $self;
}

sub _init ($) {
	my $self = shift;

	$self->set_border_width(3);
	$self->append_archive_list_page for 0 .. 2;
	$self->rescan;

	$self->show_all;
}

sub update_status ($;$) {
	my $self = shift;
	my $page_n = @_ ? shift : $self->get_current_page;
	my $msg = $page_n == PAGE_REGIST? "": $page_n == PAGE_MIRROR?
		$self->{mirror_status}: $self->{search_status};
	$self->{window}->set_status($msg);
}

sub append_archive_list_page ($) {
	my $self = shift;
	my $page_n = $self->get_n_pages;

	my $model = Gtk2::ListStore->new(('Glib::String') x 2);
	my $view = Gtk2::TreeView->new_with_model($model);
	push @{$self->{views}  ||= []}, $view;
	push @{$self->{models} ||= []}, $model;

	foreach my $i (0 .. 1) {
		my $column = Gtk2::TreeViewColumn->new_with_attributes(
			(COLUMN_LABELS)[$i], Gtk2::CellRendererText->new, text => $i,
		);
		$column->set_resizable(FALSE);
		$column->set_sort_column_id($i);
		$view->append_column($column);
	}
	$self->append_page(
		ArchWay::Widget::FrameScroll->new($view, undef, 1),
		(PAGE_LABELS)[$page_n]
	);

	$view->signal_connect(focus_in_event => sub {
		$self->fetch_suppermirror_archives;
	}) if $page_n == PAGE_MIRROR;
}

sub populate_archive_list ($$$) {
	my $self = shift;
	my $archives = shift || return;
	my $page_n = shift;
	my $model = $self->{models}->[$page_n] || die;

	$model->clear;
	foreach my $archive (sort keys %$archives) {
		my $location = $archives->{$archive};
		my $iterator = $model->append;
		$model->set($iterator, 0, $archive, 1, $location);
	}
}

sub rescan ($) {
	my $self = shift;

	my $archives = $self->{registry}->registered_archives;
	$self->{archives} = $archives;
	$self->populate_archive_list($archives, 0);
}

sub selection_signal_connect ($@) {
	my $self = shift;
	$self->{views}->[$_]->get_selection->signal_connect(@_) for 0 .. 2;
}

sub get_selected_data ($) {
	my $self = shift;
	my $view = $self->get_nth_page($self->get_current_page);
	my $selection = $view->get_selection;
	return undef unless $selection->count_selected_rows == 1;
	my ($model, $iterator) = $selection->get_selected;
	my ($archive, $location) = $model->get($iterator, 0, 1);
	return [$archive, $location];
}

sub is_archive_registered ($) {
	my $self = shift;
	my $archive = shift;
	return $self->{archives}->{$archive};
}

sub register_archive ($$$) {
	my $self = shift;
	my $archive = shift || undef;
	my $location = shift || die "No archive location";
	$self->{registry}->register_archive($location, $archive);
	$self->rescan;
}

sub unregister_archive ($$) {
	my $self = shift;
	my $archive = shift;
	$self->{registry}->unregister_archive($archive);
	$self->rescan;
}

sub web_error ($) {
	my $self = shift;
	my $error = $self->{registry}->web_error || return undef;
	$error =~ s/\n$//;
	$error =~ s/\n/ /g;
	return $error;
}

sub fetch_suppermirror_archives ($) {
	my $self = shift;
	return if $self->{mirror_queried};
	$self->{mirror_queried} = 1;

	my $registry = $self->{registry};
	my $archives = $registry->supermirror_archives;
	$self->{mirror_archives} = $archives;
	$self->populate_archive_list($archives, 1);
	$self->{mirror_status} = $self->web_error
		|| "Supermirror lists " . keys(%$archives) . " archives";
	$self->update_status;
}

sub perform_search ($$$) {
	my $self = shift;
	my $archive_re = shift;
	my $version_re = shift;

	my $archive_versions =
		$self->{registry}->search_supermirror($archive_re, $version_re, 'hashref');

	my $num = keys %$archive_versions || "no";
	$self->{search_status} = $self->web_error || "Your search results in $num archives";

	$self->fetch_suppermirror_archives;
	my $archives = {};
	foreach my $archive (sort keys %$archive_versions) {
		$archives->{$archive} = $self->{mirror_archives}->{$archive} || "";
	}

	# ignore versions for now
	$self->populate_archive_list($archives, 2);

	$self->set_current_page(PAGE_SEARCH);
	$self->update_status;
}

1;

__END__
