#!/usr/bin/perl

use strict;
use warnings;
use Math::Trig;
use POSIX qw(strftime);

### user configuration required here ###
my $debugon = 0;
my $irpg_db = '/home/superkuh/app_installs/idlerpg/irpg.db'; # idlerpg database file
my $file_path = "/home/superkuh/app_installs/idlerpg/questinfo.txt"; # idlerpg generated current quest file
my $basemapfilepath = '/home/superkuh/www/newmap.png'; # the base idlerpg world map
my $worldmapfilepath = '/home/superkuh/www/worldmap.png'; # the actual worldmap file you want
my $playerstxtfilepath = '/home/superkuh/www/players.html'; # optional html fragment, set undef or '' to disable
### user configuration ends here ###

my %players;

# cp map anew then write names on top of it
print "copying $basemapfilepath to $worldmapfilepath\n" if $debugon;
`cp $basemapfilepath $worldmapfilepath`;

open(my $file, "<", $irpg_db) or die "Cannot open file: $!";
<$file>; # Skip the first line

# fill %players
while (my $line = <$file>) {
    chomp $line;
    my @fields = split(/\t/, $line);
    
    print "-------------\n\n" if $debugon;
    if ($debugon) {print "$_ ," foreach @fields;}
    print "-------------\n\n" if $debugon;
    
    #my ($nick, $level, $class, $online, $x, $y) = @fields[0, 3, 4, 8, 10, 11];    
    #my ($nick, $level, $class, $online, $idledtime, $x, $y, $lastlogin, $weapon) = @fields[0, 3, 4, 8, 9, 10, 11, 20, 30];
    my ($nick, $level, $class, $online, $idledtime, $x, $y, $lastlogin, $amulet, $charm, $helm, $boots, $gloves, $ring, $leggings, $shield, $tunic, $weapon) = @fields[0, 3, 4, 8, 9, 10, 11, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30];

    my @colors = qw(red green blue purple brown DarkCyan);
	my $color = $colors[rand @colors];
    
	print "nick: $nick $level - online:$online, x:$x, y:$y, idled: $idledtime, lastlogin: $lastlogin, weapon: $weapon\n" if $debugon;
	$players{$nick}{x} = $x;
	$players{$nick}{y} = $y;
	$players{$nick}{level} = $level;
	$players{$nick}{class} = $class;
	$players{$nick}{color} = $color;
	$players{$nick}{online} = $online;
	$players{$nick}{idled} = $idledtime;
	$players{$nick}{lastlogin} = $lastlogin;
	$players{$nick}{weapon} = $weapon;
	$players{$nick}{tunic} = $tunic;
	$players{$nick}{shield} = $shield;
	$players{$nick}{leggings} = $leggings;
	$players{$nick}{ring} = $ring;
	$players{$nick}{gloves} = $gloves;
	$players{$nick}{boots} = $boots;	
	$players{$nick}{helm} = $helm;
	$players{$nick}{charm} = $charm;
	$players{$nick}{amulet} = $amulet;
	
}
close($file);

# generate command string for imagemagick convert from all %players
createimage(); # <- %players

sub createimage { # do all of it at once instead of many convert calls serially
	my $converttextstrings;
	my $playersfilehandle;
	
	if ($playerstxtfilepath) {
		open($playersfilehandle, '>', $playerstxtfilepath) or die "Can't open $playerstxtfilepath: $!";
		print $playersfilehandle "<ul>\n";
	} 
	
	foreach my $playernick (keys %players) {
		my $x = $players{$playernick}{x};
        my $y = $players{$playernick}{y};
        my $belowylevel = $y+20; 
        my $level = $players{$playernick}{level};
       	my $class = $players{$playernick}{class};
       	my $color = $players{$playernick}{color};  	
       	my $online = $players{$playernick}{online};
       	#my $idledtime = $players{$playernick}{idled};
		my $idledtime = duration($players{$playernick}{idled});
		#my $realidledtime = $playernick}{idled} / 60 / 60;
		my $lastlogin = $players{$playernick}{lastlogin};
		$lastlogin = strftime("%Y-%m-%d %H:%M:%S", localtime($lastlogin));
		my $weapon = $players{$playernick}{weapon};	
		my $tunic = $players{$playernick}{tunic};
		my $shield = $players{$playernick}{shield};
		my $leggings = $players{$playernick}{leggings};
		my $ring = $players{$playernick}{ring};
		my $gloves = $players{$playernick}{gloves};
		my $boots = $players{$playernick}{boots};
		my $helm = $players{$playernick}{helm};
		my $charm = $players{$playernick}{charm};
		my $amulet = $players{$playernick}{amulet};
		
       	
       	my $onorofflinestring;
       	my $yuponlineboldtag = "<b>";
       	my $yuponlineboldtag2 = "</b>";
       	if ($online) {
       		$onorofflinestring = "... is <b>online</b>";
       	} else {
       		$onorofflinestring = "... is offline since $lastlogin";
       		$yuponlineboldtag = "";
       		$yuponlineboldtag2 = "";  		
       	}
       	
       	if ($playerstxtfilepath) {
       		#print $playersfilehandle "<li>$playernick $onorofflinestring (\@$x,$y) - level: $level, class: $class</li>\n"; 
       		print $playersfilehandle "<li>$yuponlineboldtag $playernick $yuponlineboldtag2 $onorofflinestring (\@$x,$y) - total idle time: $idledtime, level: $level, class: $class, weapon: $weapon, shield: $shield, helm: $helm, tunic: $tunic, leggings: $leggings, gloves: $gloves, boots: $boots, ring: $ring, amulet: $amulet, charm: $charm</li>\n"; 
       	}
       	
   		if ($online == 1) {
   			print "nick: $playernick $level - online:$online, x:$x, y:$y\n" if $debugon;
     		if (istheplayerontopofanyother($playernick)) {
       			$color = $players{$playernick}{color};  # istheplayerontopofanyother() updates this
       			$converttextstrings .= "-pointsize 18 -fill $color -stroke $color -draw \"text $x,$y \'$playernick\'\" -pointsize 10 -fill $color -stroke $color -draw \"text $x,$belowylevel \'$level $class\'\" ";   	 
       		} else {
       			$converttextstrings .= "-pointsize 18 -fill $color -stroke $color -draw \"text $x,$y \'$playernick\'\" -pointsize 10 -fill $color -stroke $color -draw \"text $x,$belowylevel \'$level $class\'\" ";
       		}
     	} else {
        	print "nick: $playernick - offline:$online, x:$x, y:$y\n" if $debugon;
        	$converttextstrings .= "-pointsize 10 -fill black -stroke black -draw \"text $x,$y \'$playernick\'\" ";
    	}   	
	}  	
	# actually make the image
    `convert $worldmapfilepath -gravity NorthWest $converttextstrings $worldmapfilepath`;
    
    if ($playerstxtfilepath) {
    	# finish off the players html fragment
    	print $playersfilehandle "</ul>\n"; 	
    	close($playersfilehandle) or die "Can't close $playerstxtfilepath: $!";	
    }
}

# this doesn't work reliably and it's computationally terrible but better than nothing
sub istheplayerontopofanyother { # if (istheplayerontopofanyother($nick)) { ...
	my $player1 = shift;
	my $distance;
	my $radius = 100;

    my $numkeys = scalar keys %players;
    print "num players: $numkeys\n" if $debugon;
    foreach my $player2 (keys %players) {
    	print "player2: $player2\n" if $debugon;
    	next unless $players{$player1}{online};
        next if $player1 eq $player2; # Skip calculating distance to self

        my $x1 = $players{$player1}{x};
        my $y1 = $players{$player1}{y};
        my $x2 = $players{$player2}{x};
        my $y2 = $players{$player2}{y};

        $distance = sqrt(($x2 - $x1) ** 2 + ($y2 - $y1) ** 2);
        print "Distance between $player1 and $player2: $distance\n" if $debugon;  
        if ($distance < $radius) {
    		if ($players{$player1}{color} eq $players{$player2}{color}) {
    		    my @newcolors = qw(red green blue purple brown DarkCyan);
    		    @newcolors = grep { $_ ne $players{$player2}{color} } @newcolors;
        		my $fart = $newcolors[rand @newcolors];
        		$players{$player1}{color} = $fart;
    		} 
    	}
    }
    if ($distance < $radius) {
    	return 1;
    } else {
    	return 0;
    }
}

sub duration { # return human duration of seconds
    my $s = shift;
    return "NA ($s)" if $s !~ /^\d+$/;
    return sprintf("%d day%s %02d:%02d:%02d",$s/86400,int($s/86400)==1?"":"s",
                   ($s%86400)/3600,($s%3600)/60,($s%60));
}
