# 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::Merge;

use base qw(ArchWay::MainWindow::Base ArchWay::MainWindow::RevisionBase);

use Glib qw(TRUE FALSE);
use Gtk2;

use ArchWay::Widget::PartnerVersions;
use ArchWay::Widget::FrameScroll;

use Arch::Util qw(standardize_date parse_creator_email);

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

	$self->SUPER::init;
	$self->add_revision_actions;

	# menus (name, stock id, label)
	my @menus = (
		[ "FileMenu", undef, "_File" ],
		[ "PartnerMenu", undef, "_Partners" ],
		[ "RevisionMenu", undef, "_Revision" ],
	);

	# items (name, stock id, label, accelerator, tooltip, callback)
	my @items = (
		[
			"Rescan", "gtk-refresh", "_Rescan Tree",
			undef, "Find new log versions and revisions in the tree",
			sub { $self->rescan }
		],
		[
			"Add", "gtk-add", "Add",
			undef, "Add Partner Version",
			sub { $self->set_status("Not yet implemented") }
		],
		[
			"Remove", "gtk-remove", "_Remove",
			undef, "Remove Partner Version(s)",
			sub { $self->set_status("Not yet implemented") }
		],
		[
			"Hide", "gtk-no", "_Hide",
			undef, "Hide Partner Version(s)",
			sub { $self->partner_method('hide_selected') }
		],
		[
			"Unhide", "gtk-yes", "_Unhide",
			undef, "Unhide Partner Version(s)",
			sub { $self->partner_method('unhide_selected') }
		],
		[
			"Edit", "gtk-paste", "_Edit Info",
			undef, "Edit Partner Version Info",
			sub { $self->partner_method('edit_selected') }
		],
		[
			"Save", "gtk-save", "_Save Infos",
			undef, "Save Partner Versions Info",
			sub { $self->partner_method('save') }
		],
		[
			"Reload", "gtk-refresh", "_Reload Infos",
			undef, "Reload Partner Versions Info",
			sub { $self->partner_method('reload') }
		],
		[
			"SelectAll", "gtk-dnd-multiple", "Select _All",
			"<control>A", "Select All Partner Versions",
			sub { $self->partners_view->select_all }
		],
		[
			"Missing", "gtk-find", "_Missing",
			"<control>M", "What revisions are missing from selected Partner Version(s)",
			sub { $self->query_missing_revisions }
		],
		[
			"Merge", "gtk-find-and-replace", "Merge",
			"<control>S", "Perform star-merge with selected Partner Version",
			sub { $self->set_status("Not yet implemented") }
		],
	);

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

				<placeholder name="ApplicationMenus">
					<menu action="PartnerMenu">
						<menuitem action="Add" />
						<menuitem action="Remove" />
						<menuitem action="Hide" />
						<menuitem action="Unhide" />
						<separator />
						<menuitem action="Edit" />
						<menuitem action="Save" />
						<menuitem action="Reload" />
						<separator />
						<menuitem action="SelectAll" />
						<menuitem action="Missing" />
						<menuitem action="Merge" />
					</menu>
					<menu action="RevisionMenu">
						<menuitem action="GetTree" />
						<menuitem action="GetCSet" />
						<menuitem action="ViewCSet" />
						<menuitem action="ViewLog" />
					</menu>
				</placeholder>
			</menubar>

			<toolbar name="ToolBar">
				<toolitem action="Edit" />
				<separator />
				<toolitem action="Missing" />
				<toolitem action="Merge" />
				<separator />
				<toolitem action="GetTree" />
				<toolitem action="GetCSet" />
				<toolitem action="ViewCSet" />
				<toolitem action="ViewLog" />
			</toolbar>
		</ui>
	};

	# add menu/toolbar to ui
	my $actions = Gtk2::ActionGroup->new("MergeActions");
	$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->set_status("Tree version: " . $self->tree->get_version);
}

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

	return $self->{tree};
}

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

	my $partners_view  = $self->partners_view;
	my $revisions_view = $self->revisions_view;

	my $widget = Gtk2::VPaned->new;
	$widget->set_border_width(3);
	$widget->set_size_request(600, 440);
	$widget->add1(ArchWay::Widget::FrameScroll->new($self->partners_view, "Partner Versions", 1));
	$widget->add2(ArchWay::Widget::FrameScroll->new($self->revisions_view, "Revisions", 1));
	$widget->set_position(180);

	$self->sync_partner_actions;

	$self->set_merged_revisions;

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

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

	my $partners_view = ArchWay::Widget::PartnerVersions->new(
		$self->tree, $self
	);

	$partners_view->get_selection->set_mode('multiple');
	$partners_view->get_selection->signal_connect(
		changed => sub { $self->change_partner; },
	);
	$partners_view->signal_connect(
		row_activated => sub { $self->add_missing_revisions; },
	);

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

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

	$self->sync_partner_actions;
	$self->revisions_view->clear;

	my @versions = $self->partners_view->get_selected_versions;
	return unless @versions == 1;

	my $version = $versions[0];

	my $revision_descs = $self->tree->get_log_revision_descs($version);
	foreach (@{$revision_descs}) {
		my $rvsn = $_->{version} . "--" . $_->{name};
		$_->{is_merged} = $_->{is_missing} = 1
			if $self->{merged_revisions}->{$rvsn};
	}
	$self->revisions_view->add_revision_descs($revision_descs);

	$self->add_missing_revisions(1);
}

sub add_missing_revisions ($;$) {
	my $self = shift;
	my $only_existing = shift || 0;

	my @versions = $self->partners_view->get_selected_versions;
	return unless @versions == 1;

	my $version = $versions[0];
	return if ($self->{queried_versions} ||= {})->{$version} xor $only_existing;

	$self->revisions_view->add_revision_descs(
		$self->tree->get_missing_revision_descs($version),
		version => $version, is_missing => 1,
	);

	$self->{queried_versions}->{$version} = 1;
}

sub query_missing_revisions ($) {
	my $self = shift;
	my @versions = $self->partners_view->get_selected_versions;
	return unless @versions;

	my $tree = $self->tree;
	foreach my $version (@versions) {
		$tree->get_missing_revision_descs($version);
	}
	$self->add_missing_revisions;
}

sub sync_partner_actions ($) {
	my $self = shift;
	my $partners_view = $self->partners_view;
	print ++$main::line, ": (un)selected partner versions\n" if $ENV{DEBUG2};

	my $num_rows = $partners_view->get_selection->count_selected_rows;
	$self->set_widget_sensitivity(
		$num_rows == 1,
		qw(/ToolBar/Edit    /MenuBar/ApplicationMenus/PartnerMenu/Edit),
		qw(/ToolBar/Merge   /MenuBar/ApplicationMenus/PartnerMenu/Merge),
	);
	$self->set_widget_sensitivity(
		$num_rows >= 1,
		qw(/ToolBar/Hide    /MenuBar/ApplicationMenus/PartnerMenu/Hide),
		qw(/ToolBar/Unhide  /MenuBar/ApplicationMenus/PartnerMenu/Unhide),
		qw(/ToolBar/Remove  /MenuBar/ApplicationMenus/PartnerMenu/Remove),
		qw(/ToolBar/Missing /MenuBar/ApplicationMenus/PartnerMenu/Missing),
	);
	$self->set_widget_sensitivity(
		$partners_view->is_changed,
		qw(/ToolBar/Save    /MenuBar/ApplicationMenus/PartnerMenu/Save),
		qw(/ToolBar/Reload  /MenuBar/ApplicationMenus/PartnerMenu/Reload),
	);
}

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

	my $merged_revisions = $self->tree->get_merged_revisions;
	$self->{merged_revisions} = { map { $_ => 1 } @$merged_revisions };
}

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

	# rescan tree versions
	$self->partners_view->rescan;

	# reset caching of logs

	# reset missing revisions cached by Arch::Tree
	$self->tree->clear_cache;

	# reset revisions that are merged into the tree
	$self->set_merged_revisions;

	$self->change_partner;
}

sub partner_method ($$) {
	my $self = shift;
	my $name = shift;

	$self->partners_view->$name();
	$self->sync_partner_actions;
}

1;

__END__
