#!/usr/local/bin/perl

use Encode;
use Encode::JP;

# Environmental variables
# ----------------------------------------------------------------------
$thiscgi = "http://www.tkl.iis.u-tokyo.ac.jp/~toyoda/cgi-bin/maplot.cgi";
$toppage = "http://www.tkl.iis.u-tokyo.ac.jp/~toyoda/maplot.html";
$dataurl = "http://www.tkl.iis.u-tokyo.ac.jp/~toyoda/maplot";

$logfile = "/home/toyoda/WWW/.cgi-bin/maplot.log";
$cntfile = "/home/toyoda/WWW/.cgi-bin/maplot.cnt";
$comfile = "/home/toyoda/WWW/.cgi-bin/maplot.com";
$kwdfile = "/home/toyoda/WWW/.cgi-bin/maplot.kwd";

$datadir = "/home/toyoda/WWW/.cgi-bin/maplot.data";

$cgibin="/home/toyoda/WWW/.cgi-bin";
$GMTbin="/home/toyoda/tmp/GMT3.4.2/bin";
$mapath="/home/toyoda/WWW/maplot";

# Display parameters
# ----------------------------------------------------------------------
$lastN = 1000;
$lastDay = 2;

# Checking simultaneous accesses in second
# time() is used for managing map image files
# ----------------------------------------------------------------------
$time = time;

if (-e $mapath/$time.eps || -e $mapath/$time.png || -e $mapath/$time.jpg) {
  print "Content-Type: text/html\n\n";
  print "<a href=\"$toppage\">しばらく待ってここからアクセスし直してください。</a>\n";
  exit;
}

# Retrieving CGI parameters
# ----------------------------------------------------------------------
$hostaddr = $ENV{"REMOTE_ADDR"};

$useragent = $ENV{"HTTP_USER_AGENT"};
$useragent =~ s/ /;/g;
$useragent =~ s/　/;/g;

my $imgtype = 'png';
if ($useragent =~ /DoCoMo/) {
  $imgtype = 'jpg';
}

if ($ENV{'REQUEST_METHOD'} eq "POST") {
    read(STDIN, $alldata, $ENV{'CONTENT_LENGTH'});
} else {
    $alldata = $ENV{'QUERY_STRING'};
}

if ($alldata ne "") {
    foreach $data (split(/&/, $alldata)) {
	($key, $val) = split(/=/, $data);
	$val =~ tr/+/ /;
	$val =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("C", hex($1))/eg;
	$param{$key} = $val;
    }
    if ($ENV{'REQUEST_METHOD'} eq "GET") {
	if (defined($param{"com"}) && $param{"mode"} ne 'google') {
	    print "Content-Type: text/html\n\n";
	    print "<a href=\"$toppage\">ここからアクセスし直してください。</a>\n";
	    exit;
	}
    }
} else {
    print "Content-Type: text/html\n\n";
    print "<a href=\"$toppage\">ここからアクセスし直してください。</a>\n";
    exit;
}

sub is_willcom {
  my ($useragent) = @_;
  if ($useragent =~ /AH/ ||
      $useragent =~ /WILLCOM/ ||
      $useragent =~ /KYOCERA\/WX/ ||
      $useragent =~ /WS0/
  ) {
    return 1;
  } else {
    return 0;
  }
}


$logtime = $param{"time"};
$mode = $param{"mode"};
$zoom = $param{"zoom"};
$compos = $param{"compos"};
$comment = $param{"com"};
$pos = $param{"pos"};

# Checking position parameters
# ----------------------------------------------------------------------
my ($north, $east) = (undef, undef);

if (defined($pos) && $pos ne "") {
  $position = $pos;
  $position =~ /N([^E]*)E(.*)/;
  $north = $1;
  $east = $2;
} elsif ($useragent =~ /DoCoMo/) {
  $north = $param{'lat'};
  $east = $param{'lon'};
  if (!defined($north)) {
      $north = $param{'LAT'};
      $east = $param{'LON'};
  }
  $north =~ s/^.//; # remove +- on the head supporting only japanese
  $east =~ s/^.//;
  $position = "N${north}E${east}";
} elsif ($useragent =~ /KDDI/) {
  $north = $param{"lat"};
  $east = $param{"lon"};
  $north =~ s/^.//; # remove +- on the head the head supporting only japanese
  $east =~ s/^.//;
  $position = "N${north}E${east}";
} elsif (is_willcom($useragent)) {
  $position = $pos;
  $position =~ /N([^E]*)E(.*)/;
  $north = $1;
  $east = $2;
}

if ($north eq "999.99.99.999") {
    print "Content-Type: text/html\n\n";
    print "位置情報取得に失敗しました。\n";
    exit;
}

if (!defined($north) || !defined($east)) {
    print "Content-Type: text/html\n\n";
    print "Air H Phone、au、SA700iSからしかアクセスできません\n";
    exit;
}

# Checking intermittent accesses by IP
# ----------------------------------------------------------------------
if (0) {
if (!defined($mode)) {
    open(TAIL, "tail -10 $logfile |");
    while (defined($line = <TAIL>)) {
	my ($n1, $e1, $sz, $n2, $e2, $t, $addr, $ua) = split(" ", $line);
	if ($hostaddr eq $addr) {
	    print "Content-Type: text/html\n\n";
	    print "同じIPからのご利用はしばらくできません。\n";
	    close(TAIL);
	    exit;
	}
    }
    close(TAIL);
} elsif (defined($comment)) {
    open(TAIL, "tail -10 $comfile |");
    while (defined($line = <TAIL>)) {
	my ($e, $n, $lt, $ha, $cmt) = split(" ", $line);
	if ($hostaddr eq $ha) {
	    print "Content-Type: text/html\n\n";
	    print "同じIPからのコメントはしばらくできません。\n";
	    close(TAIL);
	    exit;
	} elsif ($comment eq $cmt) {
	    print "Content-Type: text/html\n\n";
	    print "同じコメントの投稿はしばらくできません。\n";
	    close(TAIL);
	    exit;
	}
    }
    close(TAIL);
}
}

# Utilities for Google Local
# ----------------------------------------------------------------------
sub redirect_to_google_local {
  open(KWDFILE, ">>$kwdfile");
  flock(KWDFILE,2);
  print KWDFILE "$east $north $time $hostaddr $useragent $comment\n";
  flock(KWDFILE,8);
  close(KWDFILE);

  $north =~ /([0-9]*)\.([0-9]*)\.([0-9]*)\.([0-9])*/;
  $n = $1 + $2 / 60 + $3 / (60 * 60) + $4 / (60 * 60 * 1000);
  $east  =~ /([0-9]*)\.([0-9]*)\.([0-9]*)\.([0-9])*/;
  $e = $1 + $2 / 60 + $3 / (60 * 60) + $4 / (60 * 60 * 1000);

  $comment = decode('sjis', $comment);
  $comment = encode('utf-8', $comment);

  print "Location: http://www.google.co.jp/imode?site=local&near=${n},${e}&q=$comment\n\n";
  exit;
}

sub print_google_keywords {
  print "<br>最近の周辺検索語:";
  open(FILE, "tail $kwdfile |");
  my $num = 0;
  my $maxkwd = 20;
  my %khash =();
  while (defined($line = <FILE>) && $num < $maxkwd) {
    chomp($line);
    my ($e, $n, $lt, $ha, $ua, @keyw) = split(" ", $line);
    if (!defined($khash{"@keyw"})) {
      $khash{"@keyw"} = 1;
      my $nc = transcoord($n);
      my $ec = transcoord($e);
      if ((!defined($mode) || $zoom == 0) ||
	  ($WEST < $ec && $ec < $EAST && $SOUTH < $nc && $nc < $NORTH)) {

	print "<a href=\"$thiscgi?time=$time&mode=google&pos=$position&com=@keyw\">@keyw</a>,";
#      $north =~ /([0-9]*)\.([0-9]*)\.([0-9]*)\.([0-9])*/;
#      $n = $1 + $2 / 60 + $3 / (60 * 60) + $4 / (60 * 60 * 1000);
#      $east  =~ /([0-9]*)\.([0-9]*)\.([0-9]*)\.([0-9])*/;
#      $e = $1 + $2 / 60 + $3 / (60 * 60) + $4 / (60 * 60 * 1000);
#      print "<a href=\"http://www.google.co.jp/imode?site=local&near=${n},${e}&q=@keyw\">@keyw</a>,";
	++$num;
      }
    }
  }
  close(FILE);
  if ($num == 0) { print "なし"; }
  print "<br>\n";
}

sub print_google_form {
  print "<form method=\"POST\" action=\"$thiscgi\">\n";
  print "<input type=\"hidden\" name=\"time\" value=\"$time\">\n";
  print "<input type=\"hidden\" name=\"mode\" value=\"google\">\n";
  print "<input type=\"text\" name=\"com\" value=\"\" size=6>\n";
  print "<input type=\"hidden\" name=\"pos\" value=\"$position\">\n";
  print "<input type=\"submit\" value=\"Google Local\"><br>\n";
  print "</form>\n";
}

if ($mode eq 'google') {
  redirect_to_google_local();
}

# Opening and locking log files
# ----------------------------------------------------------------------
open(LOGFILE, ">>$logfile");
flock(LOGFILE,2);

open(CNTFILE, "+<$cntfile");
flock(CNTFILE,2);

open(COMFILE, ">>$comfile");
flock(COMFILE,2);

$count = <CNTFILE>;
chomp $count;
($ahcnt, $aucnt, $dccnt) = split(" ", $count);
unless (defined($dccnt)) { $dccnt = 0; } # for the first access

if (!defined($mode)) {
    # write log
    print LOGFILE "0 0 0 $east $north $time $hostaddr $useragent\n";
    # increment counter
    if ($useragent =~ /KDDI/) {
      ++$aucnt;
    } elsif ($useragent =~ /DoCoMo/) {
      ++$dccnt;
    } elsif (is_willcom($useragent)) {
      ++$ahcnt;
    }
    seek(CNTFILE,0,0);
    print CNTFILE "$ahcnt $aucnt $dccnt\n";
} else {
    # write comment
    $comment =~ s/ //g;
    $comment =~ s/　//g;
    if (!($comment eq "")) {
	print COMFILE "$east $north $logtime $hostaddr $comment $useragent\n";
    }
}

sub transcoord {
  my ($coord) = @_;
  $coord =~ /([0-9]*)\.([0-9]*)\.([0-9]*)\.[0-9]*/;
  return sprintf("%d.%06d", $1, int(($2 / 60 + $3 / 3600) * 1000000));
}

sub plot_lines_by_segfiles {
  my ($WEST, $EAST, $SOUTH, $NORTH, $dir, $pen, $file) = @_;

  my ($w, $e, $s, $n) = (int($WEST), int($EAST), int($SOUTH), int($NORTH));
  my %checkhash = ();
  my ($x, $y);
  for ($x = $w; $x <= $e; ++$x) {
    for ($y = $s; $y <= $n; ++$y) {
      my $f = "$dir/N${y}E${x}.dat";
      if (-e "$f" && !defined($checkhash{$f})) {
	system("HOME=/tmp; export HOME; $GMTbin/psxy -R$WEST/$EAST/$SOUTH/$NORTH -JM4.5c -M -W$pen -O -K < $f >> $file");
	$checkhash{$f} = 1;
      }
    }
  }
}

if (!defined($mode) || $zoom == 0 || $zoom == 1) {
    $zoom = 0;
    system("HOME=/tmp; export HOME; $GMTbin/pscoast -R123.5/146/24/46 -JM4.5c -Dl -G230 -W1 -P -K -X0c -Y0c > $mapath/$time.eps");
} else {
    my $nc = transcoord($north);
    my $ec = transcoord($east);
    ($WEST, $EAST, $SOUTH, $NORTH) = ($ec - 11.25 * $zoom, $ec + 11.25 * $zoom, $nc - 11.0 * $zoom, $nc + 11.0 * $zoom);
    if (0.01 < $zoom) {
      system("HOME=/tmp; export HOME; $GMTbin/pscoast -R$WEST/$EAST/$SOUTH/$NORTH -JM4.5c -Di -G230 -W1 -P -K -X0c -Y0c > $mapath/$time.eps");
    } else {
      system("HOME=/tmp; export HOME; $GMTbin/psbasemap -R$WEST/$EAST/$SOUTH/$NORTH -JM4.5c -G230 -P -K -X0c -Y0c > $mapath/$time.eps");
      plot_lines_by_segfiles($WEST, $EAST, $SOUTH, $NORTH, $datadir, "2", "$mapath/$time.eps");
    }
    plot_lines_by_segfiles($WEST, $EAST, $SOUTH, $NORTH, "$datadir/train" , "2/0/128/0", "$mapath/$time.eps");
}

system("HOME=/tmp ; export HOME ; tail -${lastN} $logfile | $cgibin/xytrans-mc.pl 0.2 $lastDay | $GMTbin/psxy -R -JM4.5c -W1 -P -L -S -G255/0/0 -O -K >> $mapath/$time.eps");

$MaxCom = 5;
@colors = ("0/0/255", "255/255/0", "0/255/255", "255/0/255", "0/0/0");
@htcolors = ("#0000ff", "#ffff00", "#00ffff", "#ff00ff", "#000000");

flock(COMFILE,8);
close(COMFILE);

unless (defined($compos)) { $compos = 0; }

#open(FILE, "tail -r $comfile | tail +$compos |");
open(FILE, "tail $comfile |");
$Ncom = 0;
$Nlines = 0;
while (defined($line = <FILE>) && $Ncom < $MaxCom) { # new to old
    chomp($line);
    my ($e, $n, $lt, $ha, $cmt, $ua, $photo) = split(" ", $line);
    my $nc = transcoord($n);
    my $ec = transcoord($e);
    if ((!defined($mode) || $zoom == 0) ||
	($WEST < $ec && $ec < $EAST && $SOUTH < $nc && $nc < $NORTH)) {
      ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($lt);
      $mon++;
      $disptime = sprintf("%d/%d %02d:%02d", $mon, $mday, $hour, $min);
      #    $disptime = sprintf("%02d:%02d", $hour, $min);
      $hc = $htcolors[$MaxCom - $Ncom - 1];
      $comarry[$Ncom] = "$disptime <font color=\"$hc\">$cmt</font>";
      $posarry[$Ncom] = "N${n}E${e}";
      if (defined($photo)) {
	$comarry[$Ncom] = $comarry[$Ncom] . "<a href=\"$dataurl/$photo\">[写]</a>";
      }
      $earry[$Ncom] = $e;
      $narry[$Ncom] = $n;
      $uarry[$Ncom] = $ua;
      ++$Ncom;
    }
    ++$Nlines;
}
close(FILE);

for ($i = $Ncom - 1; 0 <= $i; --$i) { # old to new
  my $c = $colors[$MaxCom - $i - 1];
  my $e = $earry[$i];
  my $n = $narry[$i];
  my $shape = 'c'; # circle
  my $size = '0.25';
  if ($uarry[$i] =~ /KDDI/) {
    $shape = 'tc'; # triangle
    $size = '0.25';
  } elsif (is_willcom($uarry[$i])) {
    $shape = 'cc'; # circle
    $size = '0.25';
  } elsif ($uarry[$i] =~ /DoCoMo/) {
    $shape = 'sc'; # square
    $size = '0.25';
  }
  system("HOME=/tmp; export HOME; echo \"0 0 0 $e $n\" | $cgibin/xytrans.pl $size | $GMTbin/psxy -R -JM4.5c -W1 -P -L -S${shape} -G$c -O -K >> $mapath/$time.eps");
#    system("HOME=/tmp; export HOME; echo \"0 0 0 $e $n\" | $cgibin/xytrans.pl 0.3| $GMTbin/psxy -R -JM4.5c -W1 -P -L -Stc -G$c -O -K >> $mapath/$time.eps");
#    system("HOME=/tmp; export HOME; echo \"0 0 0 $e $n\" | $cgibin/xytrans.pl 0.5| $GMTbin/psxy -R -JM4.5c -W1 -P -L -Sac -G$c -O -K >> $mapath/$time.eps");
#    system("HOME=/tmp; export HOME; echo \"0 0 0 $e $n\" | $cgibin/xytrans.pl 0.2| $GMTbin/psxy -R -JM4.5c -W1 -P -L -Scc -G$c -O -K >> $mapath/$time.eps");
}

if ($useragent =~ /KDDI/) {
  $sopt = "-Stc";
  $ssz = "0.25";
} elsif (is_willcom($useragent)) {
  $sopt = "-Scc";
  $ssz = "0.25";
} elsif ($useragent =~ /DoCoMo/) {
  $sopt = "-Ssc";
  $ssz = "0.25";
}

if (!defined($mode)||$mode eq "selfz") {
  system("HOME=/tmp; export HOME; echo \"0 0 0 $east $north\" | $cgibin/xytrans.pl $ssz | $GMTbin/psxy -R -JM4.5c -W1 -P -L $sopt -G0/255/0 -O >> $mapath/$time.eps");
} elsif ($mode eq "postc") {
  $comarry[0] = "$disptime <font color=\"#00ff00\">$comment</font>";
  system("HOME=/tmp; export HOME; echo \"0 0 0 $east $north\" | $cgibin/xytrans.pl $ssz | $GMTbin/psxy -R -JM4.5c -W1 -P -L $sopt -G0/255/0 -O >> $mapath/$time.eps");
} else {
  system("HOME=/tmp; export HOME; echo \"0 0 0 0 0\" | $cgibin/xytrans.pl $ssz | $GMTbin/psxy -R -JM4.5c -W1 -P -L $sopt -G0/255/0 -O >> $mapath/$time.eps");
}

system("/home/toyoda/bin/convert -colors 256 $mapath/$time.eps $mapath/$time.$imgtype 2> /dev/null ; rm $mapath/$time.eps");

flock(LOGFILE,8);
close(LOGFILE);

flock(CNTFILE,8);
close(CNTFILE);

print "Content-Type: text/html\n\n";

# descriptions
print "<font size=\"-2\">○H\":$ahcnt △au:$aucnt □im:$dccnt</font><br>";
print "<font size=\"-2\" color=\"#00ff00\">緑:現在地</font> <font size=\"-2\" color=\"#ff0000\">赤:${lastDay}日以内</font><br>\n";
#print "<font color=\"#00ff00\">緑</font>:現在地,<font color=\"#ff0000\">赤</font>:最近${lastN},他:コメント色に対応.<br>\n";
#print "N$north<br>E$east<br>";

# zoom
print "<form method=\"POST\" action=\"$thiscgi\">\n";
print "<input type=\"hidden\" name=\"time\" value=\"$time\">\n";
if (!defined($mode) || $mode eq "selfz") {
  print "<input type=\"hidden\" name=\"mode\" value=\"selfz\">\n";
} else {
  print "<input type=\"hidden\" name=\"mode\" value=\"commz\">\n";
}
print "<input type=\"hidden\" name=\"compos\" value=\"$compos\">\n";
print "<input type=\"hidden\" name=\"pos\" value=\"$position\">\n";

@zoomstr = ("x1", "x16",  "x64",  "x128", "x256");
@zoomfac = (0,    0.0625, 0.0156, 0.0078, 0.0039);
print "<select name=\"zoom\">";
for ($i = 0; $i < 5; ++$i) {
  print "<option ";
  if ($zoomfac[$i] == $zoom || ($i == 0 && $zoom == 1)) {
    print "selected ";
  }
  print "value=\"$zoomfac[$i]\" ";
  print ">$zoomstr[$i]</option>\n";
}
print "</select>\n";
print "<input type=\"submit\" value=\"ズーム\">\n";
print "</form>";

# map
print "<img src=\"$dataurl/$time.$imgtype\">\n";

# keywords
print_google_keywords();
print_google_form();


for ($i = 0; $i < $Ncom; ++$i) { # new to old
    $str = $comarry[$i];
    $p = $posarry[$i];
    $z = $zoom;
    if ($zoom == 0) {$z = 0.0625; }
    print "<form method=\"POST\" action=\"$thiscgi\">\n";
    print "<input type=\"hidden\" name=\"time\" value=\"$time\">\n";
    print "<input type=\"hidden\" name=\"mode\" value=\"commz\">\n";
    print "<input type=\"hidden\" name=\"zoom\" value=\"$z\">\n";
    print "<input type=\"hidden\" name=\"compos\" value=\"$compos\">\n";
    print "<input type=\"hidden\" name=\"pos\" value=\"$p\">\n";

    print "<input type=\"submit\" value=\"中\">\n";
    print "$str<br>\n";
    print "</form>\n";
}

$prev = $compos + $Nlines;

print "<form method=\"POST\" action=\"$thiscgi\">\n";
print "<input type=\"hidden\" name=\"time\" value=\"$time\">\n";
print "<input type=\"hidden\" name=\"mode\" value=\"commb\">\n";
print "<input type=\"hidden\" name=\"zoom\" value=\"$zoom\">\n";
print "<input type=\"hidden\" name=\"compos\" value=\"$prev\">\n";
print "<input type=\"hidden\" name=\"pos\" value=\"$position\">\n";
print "<input type=\"submit\" value=\"前${MaxCom}人分コメント\">\n";
print "</form>\n";


print "<hr>\n";
print "<form method=\"POST\" action=\"$thiscgi\">\n";
print "<input type=\"hidden\" name=\"time\" value=\"$time\">\n";
print "<input type=\"hidden\" name=\"mode\" value=\"postc\">\n";
print "<input type=\"text\" name=\"com\" value=\"\" size=10>\n";
print "<input type=\"hidden\" name=\"zoom\" value=\"$zoom\">\n";
print "<input type=\"hidden\" name=\"compos\" value=\"0\">\n";
print "<input type=\"hidden\" name=\"pos\" value=\"$position\">\n";
print "<input type=\"submit\" value=\"コメント\"><br>\n";
print "</form>\n";

my $t = $time;
if (defined($logtime)) { $t = $logtime; }

print "<a href=\"mailto:mtoyoda\@acm.org?subject=E${east}N${north}T${t}\">写真を送る</a>:コメントを本文に書いて写真を1枚添付してメール送信して下さい。しばらく待つと登録されます。管理人が見て非常識な写真は削除します。<br>";
if (!defined($mode)||$mode eq "selfz") {
  my $z = $zoom;
  if (!defined($z) || $z == 0) { $z = 1; }
  print "<a href=\"mailto:?subject=$position&body=%3cimg%20src=%22http://www.tkl.iis.u-tokyo.ac.jp/~toyoda/cgi-bin/map1pt.cgi%3fp=$position%2526z=$z%22%3e\">地図画像へのリンクをメールで送る</a>:自分の位置のみをプロットした地図画像へのリンク(imgタグ)をメールで好きな所へ送ることができます。moblog等にご利用下さい。";
}

print "<hr>\n";
print "Powered by GMT and Google Local\n";
exit;
