# vim: syntax=perl

# Author:  Chao-Kuei Hung
# For more info, including license, please see doc/index.html

use strict;

my ($min, $via);

sub get_path {
    my ($s, $t) = @_;

    return () if $s eq $t;
    my (@a, @b);
    if (ref $via->{$s}{$t} eq "Vertex") {
	@a = get_path($s, $via->{$s}{$t});
	@b = get_path($via->{$s}{$t}, $t);
	return (@a,@b);
    } elsif (ref $via->{$s}{$t}) {	# linked directly by an edge
	return ($via->{$s}{$t});
    } else {				# unreachable
	return ();
    }
}

sub flwa {
    my ($gr, %opts) = @_;
    my ($n2V, @V, $e, $relay, $s, $t, $new_val, $prev,
	@old_path, @new_path);
    $n2V = $gr->cget(-vertices);
    @V = @{ $n2V }{ sort keys %$n2V };

print STDERR "Warning: This algorithm is very slow.\n" .
"Please get yourself some exercise while waiting.\n";
    foreach $s (@V) {
	foreach $e ($gr->edges_around($s)) {
	    $t = $e->target();
	    $min->{$s}{$t} = $e->cget(-weight);
	    $via->{$s}{$t} = $e;
	}
	$min->{$s}{$s} = 0;
    }

    foreach $relay (@V) {
	$gr->cget(-canvas)->set_mark(1);
print STDERR "[$relay]\n";
	foreach $s (@V) {
	    next if $s eq $relay or not defined $min->{$s}{$relay};
	    foreach $t (@V) {
		next if $t eq $relay or $t eq $s or not defined $min->{$relay}{$t};
		$new_val = $min->{$s}{$relay} + $min->{$relay}{$t};
		@old_path = defined $min->{$s}{$t} ? get_path($s,$t) : ();
		@new_path = (get_path($s,$relay), get_path($relay,$t));
		if (ref $prev->{t}) {
		    $prev->{relay}->configure(-status=>"init");
		    $prev->{s}->configure(-status=>"init");
		    $prev->{t}->configure(-status=>"init");
		    map { $_->configure(-status=>"init") } @{ $prev->{path} };
		}
		if (not defined $min->{$s}{$t}
		    or $new_val < $min->{$s}{$t}) {
		    $min->{$s}{$t} = $new_val;
		    $via->{$s}{$t} = $relay;
		    # notice drawing order: both paths may overlap
		    map { $_->configure(-status=>"discard") } @old_path;
		    map { $_->configure(-status=>"pending") } @new_path;
		} else {
		    map { $_->configure(-status=>"discard") } @new_path;
		    map { $_->configure(-status=>"pending") } @old_path;
		}
		$s->configure(-status=>"pending");
		$t->configure(-status=>"pending");
		$relay->configure(-status=>"focus");
		$gr->cget(-canvas)->set_mark(0);
		$prev = { relay=>$relay, s=>$s, t=>$t,
		    path=>[@old_path, @new_path] };
	    }
	}
    }
    $prev->{relay}->configure(-status=>"init");
    $prev->{s}->configure(-status=>"init");
    $prev->{t}->configure(-status=>"init");
    map { $_->configure(-status=>"init") } @{ $prev->{path} };
    $gr->cget(-canvas)->set_mark(0);
#foreach $s (@V) {
#foreach $t (@V) {
#print "$s=>$t : ";
#my (@p) = get_path($s,$t);
#print "@p\n";
#}
#}

}

1;

