#!/usr/bin/perl -Tw

BEGIN
  {
  $|++;				# output buffer off
  unshift @INC, 'lib';		# use local modules first
  }

$VERSION = '0.15';

use strict;
# use warnings;			# be lean
use Graph::Easy 0.34;
use Graph::Easy::Parser;

my $timeout = 5; 		# set hard timeout
 
# wrong number of options?
if (@ARGV < 2 || @ARGV > 3)
  {
  require Pod::Usage;		# do not load this unless nec.
  Pod::Usage::pod2usage(-2);	# print help and exit
  }

eval
  {
  local $SIG{ALRM} = sub { die "graphcnv took more than $timeout seconds to parse and layout graph\n" };
  alarm $timeout;

  my $parser = Graph::Easy::Parser->new();

  my ($txt, $encoding, $output) = @ARGV;

  # We do NOT check the return value, because it will be false for "A", and
  # true for "köln". (why?)

  utf8::decode($txt);

  binmode STDOUT, ':utf8' or die ("binmode STDOUT, ':utf8' failed: $!");

  my $graph = $parser->from_text($txt);		# create a graph object

  # the "\n" prevents double line nr double line nr reports
  die ($parser->error()."\n") if $parser->error();

  # if user specified output like "graph { output: ascii; }", use it
  $output = $graph->attribute('graph', 'output') unless $output;
  # fallback to html output
  $output = 'html' unless $output;
  die ("Invalid output format '$output'\n") if $output !~ /^(html|ascii|svg|boxart)\z/i;

  if ($output =~ /html/i)
    {
    my $css = "<style type='text/css'><!--\n" . $graph->css() . "--></style>";
    my $html = $graph->as_html();

    $html =~ s/\n+\z//;				# remove trailing "\n"

    # mediawiki doesn't like leading spaces and empty lines in the CSS
    $css =~ s/(^|\n)\s+/$1/g;			# spaces at front

    print $css, $html;
    }
  elsif ($output =~ /boxart/)
    {
    # output as Unicode box drawing, suitable for embedding into HTML
    print $graph->as_boxart_html();
    }
  elsif ($output =~ /ascii/)
    {
    # output as ASCII, suitable for embedding into HTML
    print $graph->as_ascii_html();
    }
  else
    {
    require Digest::SHA1;		# for hashing to a file name

    # output as SVG, suitable for embedding into HTML
    my $svg = $graph->as_svg_file();

    my $info = $graph->svg_information();
    # use sensible defaults, and sane values
    my $w = abs(int($info->{width} || 200)) + 1;
    my $h = abs(int($info->{height} || 100)) + 1;

    # Cairo has problems with bigger SVGs
    my $max = 32*1024 -1;
    $w = $max if $w > $max;
    $h = $max if $h > $max;

    # Hash the graph text representation to the filename
    # Different graphs that are equivalent will hash to the same file
    # name, thus saving us space.  
    my $sha1 = Digest::SHA1->new();
    $sha1->add($graph->as_txt());
    my $hash = $sha1->hexdigest;

    my $file = "images/graph/$hash.svg";
    open FILE, ">$file" or die ("Can't write to $file: $!");
    binmode FILE, ':utf8';
    print FILE $svg;
    close FILE;

    $svg = '<object type="image/svg+xml" width="##w##" height="##h##" data="/wiki/images/graph/##file##">' . "\n" .
           '<b>Your browser does not yet support <a title="Scalable Vector Graphics" href="/wiki/SVG">SVG</a>.</b>' . "\n" .
           "</object>\n";

    $svg =~ s/##file##/$hash.svg/g;
    $svg =~ s/##w##/$w/g;
    $svg =~ s/##h##/$h/g;

    print $svg;
    }

  # disable alarm
  alarm 0;
  };

if ($@) 
  {
  # propagate unexpected errors
  print "<strong class='error'>graphcnv error: $@</strong>\n";
  }

1;

__END__

=pod

=head1 NAME

graphcnv - convert textual graph description to ASCII/HTML

=head1 SYNOPSIS

	perl -T graphcnv graph-as-text encoding [outputtype]

Examples:

	perl -T graphcnv '[ Bonn ] --> [ Berlin ]' 'utf-8'
	perl -T graphcnv '[Bonn] --> [Berlin]' 'utf-8' 'ascii'

=head1 DESCRIPTION

Turns a given textual graph representation into a pretty graph. Uses
L<Graph::Easy> behind the scenes to do all the hard work.

The C<encoding> parameter is currently ignored, the input is expected
to be in C<utf-8>.

=head1 VERSIONS

Please see the CHANGES file for a complete version history.

=head1 LICENSE

This library is free software; you can redistribute it and/or modify
it under the same terms of the GPL version2.

See the LICENSE file for information.

=head1 AUTHOR

(c) by Tels bloodgate.com 2005

=head1 SEE ALSO

<L<Graph::Easy>, L<http://bloodgate.com/perl/graph>.

=cut
