# 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::MainWindow::Registry;

use base 'ArchWay::MainWindow::Base';

use Glib qw(TRUE FALSE);
use Gtk2;

use Arch::Registry;
use ArchWay::Widget::ArchiveRegistry::Lists;
use ArchWay::Widget::ArchiveRegistry::Entry;
use ArchWay::Widget::ArchiveRegistry::Query;
use ArchWay::Widget::FrameScroll;

sub init ($) {
	my $self = shift;
	my $cache_dir = $self->setup_config_dir("registry-cache");

	$self->{registry} = Arch::Registry->new->set_web_cache(
		dir => $cache_dir, ttl => 2 * 60 * 60,
	);

	$self->SUPER::init;

	# menus (name, stock id, label)
	my @menus = (
		[ "ArchiveMenu", undef, "_Archive" ],
		[ "FileMenu", undef, "_File" ],
	);

	# items (name, stock id, label, accelerator, tooltip, callback)
	my @items = (
		[
			"Rescan", "gtk-refresh", "Re_scan",
			undef, "Rescan registered archives",
			sub { $self->rescan },
		],
		[
			"Register", "gtk-add", "_Register",
			undef, "Register archive",
			sub { $self->register }
		],
		[
			"Unregister", "gtk-remove", "_Unregister",
			undef, "Unregister archive",
			sub { $self->unregister }
		],
		[
			"Browse", "gtk-find", "_Browse",
			undef, "Browse archive",
			sub { $self->session->activate_gui('archv', $self->entry_view->archive_name) }
		],
	);

	# menu/toolbar layout
	my $layout = <<_EOF_;
<ui>
	<menubar name="MenuBar">
		<menu action="FileMenu">
			<placeholder name="FileMenuItems">
				<menuitem action="Rescan" />
			</placeholder>
		</menu>

		<placeholder name="ApplicationMenus">
			<menu action="ArchiveMenu">
				<menuitem action="Register" />
				<menuitem action="Unregister" />
				<menuitem action="Browse" />
			</menu>
		</placeholder>
	</menubar>

	<toolbar name="ToolBar">
		<toolitem action="Rescan" />
		<toolitem action="Register" />
		<toolitem action="Unregister" />
		<toolitem action="Browse" />
	</toolbar>
</ui>
_EOF_

	# add menu/toolbar to ui
	my $actions = Gtk2::ActionGroup->new("RegistryActions");
	$actions->add_actions(\@menus, undef);
	$actions->add_actions(\@items, undef);

	$self->ui->insert_action_group($actions, 0);
	$self->ui->add_ui_from_string($layout);

	$self->sync_entry_buttons;
}

sub main_widget ($) {
	my $self = shift;
	return $self->{main_widget} if $self->{main_widget};

	my $vbox = Gtk2::VBox->new(FALSE, 0);
	$vbox->pack_start(
		ArchWay::Widget::FrameScroll->new($self->lists_view, "Archive Lists"),
		TRUE, TRUE, 0
	);
	$vbox->pack_end(
		ArchWay::Widget::FrameScroll->new($self->query_view, "Search Supermirror"),
		FALSE, FALSE, 0
	);
	$vbox->pack_end(
		ArchWay::Widget::FrameScroll->new($self->entry_view, "Active Archive"),
		FALSE, FALSE, 0
	);

	$self->set_deep_widget_focus_child($vbox);

	return $self->{main_widget} = $vbox;
}

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

	# for some reason set_no_show_all(1) does not work, so use destroy
	$self->query_view->parent->destroy;
	$self->lists_view->get_nth_page(2)->destroy;
	$self->lists_view->get_nth_page(1)->destroy;

	$self->{dialog}->signal_connect(response => sub {
		my ($dialog, $response) = @_;
		my $archive_name = $self->entry_view->archive_name;
		if ($response eq 'ok' && $archive_name && $archive_name =~ /.+@.+/) {
			print "$archive_name\n" unless $self->{is_quiet};
		} else {
			$archive_name = undef;
		}
		$self->{is_dialog}->($archive_name) if ref($self->{is_dialog}) eq 'CODE';
		$dialog->destroy; $self->destroy;
	});
	$self->sync_entry_buttons;
}

sub lists_view ($) {
	my $self = shift;
	return $self->{lists_view} if $self->{lists_view};

	my $lists_view = ArchWay::Widget::ArchiveRegistry::Lists->new(
		$self, $self->{registry}
	);

	$lists_view->selection_signal_connect(
		changed => sub { $self->update_entry_view }
	);

	$lists_view->set_size_request(500, 200);

	return $self->{lists_view} = $lists_view;
}

sub entry_view ($) {
	my $self = shift;
	return $self->{entry_view} if $self->{entry_view};

	my $entry_view = ArchWay::Widget::ArchiveRegistry::Entry->new(
		$self, $self->{registry}
	);

	$entry_view->signal_changed_connect(
		archive_name => sub { $self->sync_entry_buttons('archive_name') },
	);
	$entry_view->signal_changed_connect(
		archive_location => sub { $self->sync_entry_buttons('archive_location') },
	);

	return $self->{entry_view} = $entry_view;
}

sub query_view ($) {
	my $self = shift;
	return $self->{query_view} if $self->{query_view};

	my $query_view = ArchWay::Widget::ArchiveRegistry::Query->new(
		$self, $self->{registry}
	);

	$query_view->signal_clicked_connect(sub { $self->perform_search });

	return $self->{query_view} = $query_view;
}

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

	$self->entry_view->set_data($self->lists_view->get_selected_data);
}

sub perform_search ($) {
	my $self = shift;
	my $lists_view = $self->lists_view;
	my $query_view = $self->query_view;

	$lists_view->perform_search(
		$query_view->archive_re,
		$query_view->version_re,
	);
}

sub sync_entry_buttons ($$) {
	my $self = shift;
	my $prop = shift || "all";
	my $entry_view = $self->entry_view;
	print ++$main::line, ": changed entry $prop\n" if $ENV{DEBUG2};

	my $archive_name = $entry_view->archive_name;
	my $is_valid_name = $archive_name && $archive_name =~ /.+@.+/;

	my $archive_location = $entry_view->archive_location;
	my $is_valid_location = $archive_location && $archive_location =~ m!^(/|\w([\w-]*):)!;

	my $is_registered = $is_valid_name && $self->lists_view->is_archive_registered($archive_name);

	# weak attempt to optimize things a bit
	if ($prop eq "all" || $prop eq 'archive_name') {
		$self->set_widget_sensitivity(
			$is_valid_name && $is_registered,
			qw(
				/ToolBar/Unregister
				/ToolBar/Browse
				/MenuBar/ApplicationMenus/ArchiveMenu/Unregister
				/MenuBar/ApplicationMenus/ArchiveMenu/Browse
			)
		);
	}
	$self->set_widget_sensitivity(
		($archive_name eq "" || $is_valid_name) && $is_valid_location && !($is_registered && $is_registered eq $archive_location),
		qw(
			/ToolBar/Register
			/MenuBar/ApplicationMenus/ArchiveMenu/Register
		)
	);

	$self->{dialog}->set_response_sensitive('ok', $is_valid_name && $is_registered)
		if $self->{dialog};
}

sub rescan ($) {
	my $self = shift;
	$self->lists_view->rescan;
}

sub register ($) {
	my $self = shift;
	$self->lists_view->register_archive($self->entry_view->get_data);
	$self->sync_entry_buttons;
}

sub unregister ($) {
	my $self = shift;
	$self->lists_view->unregister_archive($self->entry_view->archive_name);
	$self->sync_entry_buttons;
}

1;

__END__
