#!/usr/bin/perl

package display_map;

use GD;
use FileHandle;
use cfgfile;

my %image_cache = ();


sub new
{
    my ($this, $display, $cfg) = @_;
    my  $class = ref($this) || $this;
    my  $self = {};

    bless($self, $class);
    $cfg = "display_map.cfg" unless( $cfg );
    $self->{"cfg"} = $cfg;
    $self->{"display"} = $display;
    print "display_map::new() created object for $cfg\n" if( $BigSister::common::dl>4 );
    return $self;
}


sub set_display {
    my( $self, $display ) = @_;

    $self->{"display"} = $display;
}


sub create {
    my ( $self ) = @_;
    my $cfg = new cfgfile( $self->{"cfg"} );
    my $seq = FileHandle->new;
    my ($cmd, $args, @args);
    my( $image, %stats, $map, $i, %colors, %positions );

    $cfg->rewind();
    print "display_map::create() for ".($cfg->current_file())."\n" if( $BigSister::common::dl>4 );
    if( open( $seq, "<".($cfg->current_file()).".seq" ) ) {
	$_ = <$seq>;
	chomp;
	$self->{"alt"} = $_+1;
	close $seq;
    }
    open( $seq, ">".($cfg->current_file()).".seq" );
    seek( $seq, 0, 0 );
    print $seq ($self->{"alt"}+1)."\n";
    close $seq;
    $self->{"map"} = $map = [];
    while( $_ = $cfg->nextline() ) {
	print "display_map::read line: $_" if( $BigSister::common::dl>7 );
	chomp;
	next if( /^#/ || ! $_);
	if( /^(template|red|green|yellow|purple|clear|blue|white|graphics|at|dump|name|line|link)[\s\t]+(.*)/ ) {
	    ($cmd, $args) = ($1,$2);
	    @args = split( /[\s\t]+/, $args );
	    if( $cmd eq "template" ) {
		print "display_map::create: read image from $args[0]\n" if( $BigSister::common::dl>5 );
		$image = $self->fromgif( $args[0] );
		last unless( $image );
		$image->interlaced(1);
		$colors{"red"} = $image->colorAllocate(255,0,0);
		$colors{"green"} = $image->colorAllocate(0,255,0);
		$colors{"yellow"} = $image->colorAllocate(255,255,0);
		$colors{"purple"} = $image->colorAllocate(255,0,255);
		$colors{"clear"} = $image->colorAllocate(228,228,228);
		$colors{"blue"} = $image->colorAllocate(0,0,255);
		$colors{"white"} = $image->colorAllocate(255,255,255);
	    }
	    elsif( grep( $cmd eq $_, "red", "green", "purple", "yellow", "blue", "clear", "white" ) ) {
		$stats{$cmd} = $self->fromgif( $args[0], 1, 1 );
		print "display_map::create: read status image $cmd from $args[0]\n" if( $BigSister::common::dl>5 );
	    }
	    elsif( $cmd eq "dump" ) {
		my( $fh, $file, $alt, $former );

		$file = $args[0];
		if( $file =~ m#^www/# ) {
		    $file = $';
		}
		$file = "$BigSister::common::fs{'web'}/$file" unless( $file =~ m#^/# );

		$fh = FileHandle->new();
		$alt = $self->{"alt"};
		if( ! ($file =~ /\.(jpg|jpeg|gif|png)$/) ) {
		    $file .= ".png";
		}
		for( $i=$alt-2; $i<=$alt; $i++ ) {
 		    $former = $file;
		    $former =~ s/\./$i\./;
		    unlink( $former );
	        }
		$alt+=2;
		$file =~ s/\./$alt\./;
		if( ($file =~ /\.(jpg|jpeg)$/) && ! defined &GD::Image::jpeg ) {
		    $file =~ s/\.jp.{0,1}g$/\.png/;
		}
		if( ($file =~ /\.png$/) && ! defined &GD::Image::png ) {
		    $file =~ s/\.png$/\.gif/;
		}
		if( ($file =~ /\.gif$/) && ! defined &GD::Image::gif ) {
		    $file =~ s/\.gif$/\.png/;
		}
		open( $fh, ">".$file ) || last;
		binmode $fh;
		($file =~ /\.png$/) && (print $fh $image->png);
		($file =~ /\.gif$/) && (print $fh $image->gif);
		($file =~ /\.(jpg|jpeg)$/) && (print $fh $image->jpeg);
		close( $fh );
		$self->{"recent_file"} = $file;
		print "display_map::create: dumped image to $args[0]\n" if( $BigSister::common::dl>5 );
	    }
	    elsif( $cmd eq "link" ) {
		my( $pos, $target, $imagefile ) = @args;
		my( $x, $y ) = $self->coord( $pos, %positions );
		my( $w, $h, $ins );

		my $file = $cfg->find_file( $imagefile );
	        $ins = $self->fromgif( $file, 1, 1 ) if( $file );
		if( $ins ) {
		    ($w,$h) = $ins->getBounds();
		    $image->copy($ins,$x-$w/2,$y-$h/2,0,0,$w,$h);
		}
		else {
		    ($w,$h) = $self->coord( $imagefile, %positions );
		}
		push( @$map, [ $x-$w/2, $y-$h/2, $w, $h, undef, $target ] );
		    
		print "display_map::create: inserted link $target at $pos\n" if( $BigSister::common::dl>5 );
	    }
	    elsif( $cmd eq "at" ) {
		my( $pos, $group, $ins ) = @args;
		my( $x, $y ) = $self->coord( $pos, %positions );
		my( $w, $h, $status );

		my $status = $self->get_status( $group );
		if( $ins = $stats{$status} ) {
		    ($w,$h) = $ins->getBounds();
		    $image->copy($ins,$x-$w/2,$y-$h/2,0,0,$w,$h);
		    push( @$map, [ $x-$w/2, $y-$h/2, $w, $h, $group ] );
		}
		print "display_map::create: inserted status $status for $group at $pos\n" if( $BigSister::common::dl>5 );
	    }
	    elsif( $cmd eq "name" ) {
		my( $pos, $name ) = @args;
		my( $x, $y ) = $self->coord( $pos, %positions );
		$positions{$name} = [$x,$y];
	    }
	    elsif( $cmd eq "line" ) {
		my( $pos1, $pos2, $group ) = @args;
		my( $status );

		$status = $self->get_status( $group );
		if( defined $colors{$status} ) {
		    my @coord1 = $self->coord( $pos1, %positions );
		    my @coord2 = $self->coord( $pos2, %positions );
		    if( ($#coord1 == 1) && ($#coord2 == 1) ) {
			$image->line( @coord1, @coord2, $colors{$status} );
			print "display_map::create: lined status $status for $group\n" if( $BigSister::common::dl>5 );
			push( @$map, [ $self->coord( $pos1, %positions ), $self->coord( $pos2, %positions ), $group, "", "line" ] );
		    }
		    else {
			print "display_map::create: bad line coordinates for $group\n" if( $BigSister::common::dl>3 );
		    }
		}
	    }
	}
    }
}

		

sub coord {
    my( $self, $pos, %positions ) = @_;

    if( defined $positions{$pos} ) {
	return( $positions{$pos}->[0], $positions{$pos}->[1] );
    }
    return( split( /[,;:,\.]/, $pos ) );
}



sub file {
    my( $self ) = @_;

    return $self->{"recent_file"};
}


sub map {
    my( $self ) = @_;

    return( $self->{"map"} ) if( $self->{"map"} );
    return( [] );
}


sub updated {
    my( $self ) = @_;
}



sub fromgif {
    my( $self, $file, $transparent, $cache ) = @_;
    my( $fh, $image );

    print "display_map::fromgif($file)\n" if( $BigSister::common::dl>5 );
    $file = BigSister::common::find_file( $file );
    print "  file is $file\n" if( $BigSister::common::dl>6 );
    if( $cache && (defined $image_cache{$file}) ) {
	return( $image_cache{$file} );
    }
    if( defined &GD::Image::png ) {
	# "new" GD module
	$image = GD::Image->new($file);
    }
    else {
	open( _GIF, "<".$file ) || return(undef);
	binmode _GIF;
	$image = GD::Image->newFromGif(_GIF);
	close( _GIF );
    }
    ($image = GD::Image->new(1,1)) unless( $image );
    if( ($image->transparent < 0) && $transparent ) {
	$image->transparent($image->colorClosest(0,0,0));
    }
    if( $cache ) {
	$image_cache{$file} = $image;
    }
    return $image;
}


sub cfg {
    my( $self, $cfg ) = @_;

    $self->{"cfg"} = $cfg if( $cfg );
    return( $self->{"cfg"} );
}


sub get_status {
    my( $self, $group ) = @_;

    my( $host, $check ) = BigSister::common::separate_service( $group );
    $status = "clear";
    if( $check ) {
	$cols = $self->{"display"}->get_checks( $host );
	$status = $self->{"display"}->get_statustext( $cols->{$check} )
	  if( defined $cols->{$check} );
    }
    else {
	$status = $self->{"display"}->group_status( $group );
    }
    return $status;
}

1;
