#!/usr/bin/perl

use warnings;
use strict;

require "text-functions.pl";

# Start out of the ocean
my($latitude)=25;
my($longitude)=0;

my($nodeid)=0;
my($wayid)=0;


#
# Subroutines
#

sub parse_txt
  {
   my($filename)=(@_);

   my(%global)=();

   $global{MINZOOM}=1;
   $global{MAXZOOM}=18;

   my($objects)=ReadText(\%global,$filename);

   my($object);

   my(%tags)=();

   foreach $object (@{$objects})
     {
      my($filter)   =$object->{FILTER};
      my($subfilter)=$object->{'SUB-FILTER'};

      my(@filters)=split(/ +(and|or) +/,$filter);

      foreach $filter (@filters)
        {
         my($primary,$value)=("","");

         if($filter =~ m%^\[([^]]+)\] *= *['"]([^'"]+)['"]$%g)
           {
            $primary=$1;
            $value=$2;
           }

         if($filter =~ m%^\[([^]]+)\] *!= *['"]['"]$%g)
           {
            $primary=$1;
            $value="random";
           }

         next if($primary eq "highway" && $value eq "proposed");

         if($primary ne "")
           {
            if($subfilter eq "")
              {
               print STDERR "$filename : $primary => $value\n";
               push(@{$tags{$primary}},{$primary=>$value, name=>"$primary=$value"});
              }
            elsif("$subfilter" =~ m%^\[([^]]+)\] *= *['"]([^'"]+)['"]$%g)
              {
               print STDERR "$filename : $primary => $value ; $1 => $2\n";
               push(@{$tags{$primary}},{$primary=>$value, $1=>$2, name=>"$primary=$value $1=$2"});
              }
            elsif("$subfilter" =~ m%^\[([^]]+)\] *!= *['"]([^'"]+)['"]$%g)
              {
               print STDERR "$filename : $primary => $value\n";
               push(@{$tags{$primary}},{$primary=>$value, name=>"$primary=$value"});
              }
            elsif("$subfilter" =~ m%^\[([^]]+)\] *= *['"]([^'"]+)['"] *or *\[([^]]+)\] *= *['"]([^'"]+)['"]$%g)
              {
               print STDERR "$filename : $primary => $value ; $1 => $2\n";
               push(@{$tags{$primary}},{$primary=>$value, $1=>$2, name=>"$primary=$value $1=$2"});
               print STDERR "$filename : $primary => $value ; $3 => $4\n";
               push(@{$tags{$primary}},{$primary=>$value, $3=>$4, name=>"$primary=$value $3=$4"});
              }
            elsif("$subfilter" =~ m%^\[([^]]+)\] *= *['"]([^'"]+)['"] *or *\[([^]]+)\] *= *['"]([^'"]+)['"] *or *\[([^]]+)\] *= *['"]([^'"]+)['"]$%g)
              {
               print STDERR "$filename : $primary => $value ; $1 => $2\n";
               push(@{$tags{$primary}},{$primary=>$value, $1=>$2, name=>"$primary=$value $1=$2"});
               print STDERR "$filename : $primary => $value ; $3 => $4\n";
               push(@{$tags{$primary}},{$primary=>$value, $3=>$4, name=>"$primary=$value $3=$4"});
               print STDERR "$filename : $primary => $value ; $5 => $6\n";
               push(@{$tags{$primary}},{$primary=>$value, $5=>$6, name=>"$primary=$value $5=$6"});
              }
            else
              {
               print STDERR "$filename : TOO COMPLICATED : $primary => $value ; $subfilter\n";
              }
           }
        }
     }

   my($primary,$tag);

   foreach $primary (sort (keys %tags))
     {
      my(%seen)=();
      my(@uniq_list)=();

      foreach $tag (@{$tags{$primary}})
        {
         if(!defined $seen{$tag->{name}})
           {
            push(@uniq_list,$tag);
            $seen{$tag->{name}}=1;
           }
        }

      $tags{$primary}=[@uniq_list];
     }

   return(%tags);
  }


sub print_node
  {
   my($lat,$lon,%tags)=(@_);

   $nodeid++;

   print "  <node id='$nodeid' version='1' visible='true' lat='$lat' lon='$lon'>\n";

   my($key);

   foreach $key (keys %tags)
     {
      print "    <tag k='$key' v='$tags{$key}' />\n";
     }

   print "  </node>\n";
  }

sub print_way
  {
   my($nodes,%tags)=(@_);

   $wayid++;

   print "  <way id='$wayid' version='1' visible='true'>\n";

   my($node);

   foreach $node (@$nodes)
     {
      print "    <nd ref='$node' />\n";
     }

   my($key);

   foreach $key (keys %tags)
     {
      print "    <tag k='$key' v='$tags{$key}' />\n";
     }

   print "  </way>\n";
  }


#
# Print a header
#

print "<?xml version='1.0' encoding='UTF-8'?>\n";
print "<osm version='0.6' generator='key.pl'>\n";


#
# Print way types
#

my($wayspacing)=0.005;
my($waylength)=0.01;

my($waylat)=$latitude +$wayspacing;
my($waylon)=$longitude+$wayspacing;

sub print_line_types
  {
   my($type,@lines)=(@_);

   my($tunnels_bridges)=1;

   my($crosslon)=$waylon;
   my($firstwaylat)=$waylat;
   my($crossway);

   foreach $crossway (@lines)
     {
      $crosslon-=$wayspacing;

      print_node($waylat-$wayspacing,$crosslon);
     }

   $nodeid++; # Just to make maths easier later

   my($way);

   foreach $way (@lines)
     {
      my(%tags)=%$way;

      print_node($waylat,$waylon+9*$waylength+0.5*$wayspacing,('osmkey:text' => $$way{name}, 'osmkey:align' => 'right'));

      print_node($waylat,$waylon+9*$waylength);

      if($tunnels_bridges)
        {
         print_node($waylat,$waylon+6*$waylength);
         print_node($waylat,$waylon+5*$waylength);
         print_node($waylat,$waylon+2*$waylength);
         print_node($waylat,$waylon+1*$waylength);
        }
      else
        {
         $nodeid+=4;
        }

      print_node($waylat,$waylon);

      if($tunnels_bridges)
        {
         my($wayn);

         foreach $wayn (1..5)
           {
            my(%tags)=%$way;
            delete $tags{name};

            $tags{ref}='Ref'     if($wayn==1);
            $tags{bridge}='true' if($wayn==2);
            $tags{layer}='1'     if($wayn==2);
            $tags{name}='Name'   if($wayn==3);
            $tags{tunnel}='true' if($wayn==4);
            $tags{layer}='-1'    if($wayn==4);

            print_way([$nodeid-6+$wayn,$nodeid-5+$wayn],%tags);
           }
        }
      else
        {
         my(%tags)=%$way;
         $tags{name}='Name';

         print_way([$nodeid-5,$nodeid],%tags);
        }

      # Print crossings

      $crosslon=$waylon;

      %tags=%$way;
      delete $tags{name};

      foreach $crossway (@lines)
        {
         $crosslon-=$wayspacing;

         print_node($waylat,$crosslon);
         print_way([$nodeid-1,$nodeid],%tags);
        }

      $crosslon=$waylon;
      my($wayn)=0;

      foreach $crossway (@lines)
        {
         $crosslon-=$wayspacing;
         $wayn++;

         my(%tags)=%$crossway;
         delete $tags{name};

         print_way([$nodeid-2*$#lines-10+$wayn,$nodeid-$#lines-1+$wayn],%tags);
        }

      print_node($waylat,$waylon-1);
      print_way([$nodeid-1,$nodeid],%tags);

      $waylat+=$wayspacing;
     }

   $crosslon=$waylon;

   foreach $crossway (@lines)
     {
      $crosslon-=$wayspacing;

      my(%tags)=%$crossway;
      delete $tags{name};

      print_node($waylat,$crosslon);
      print_way([$nodeid-$#lines-2,$nodeid],%tags);
     }

#   if($tunnels_bridges)
#     {
#      $crosslon-=2*$wayspacing;
#
#      foreach $crossway (@lines)
#        {
#         my($wayn);
#
#         foreach $wayn (1..2)
#           {
#            $crosslon-=$wayspacing;
#
#            my(%tags)=%$crossway;
#            delete $tags{name};
#
#            $tags{bridge}='true' if($wayn==1);
#            $tags{layer}='1'     if($wayn==1);
#            $tags{tunnel}='true' if($wayn==2);
#            $tags{layer}='-1'    if($wayn==2);
#
#            print_node($firstwaylat-$wayspacing,$crosslon);
#            print_node($waylat                 ,$crosslon);
#            print_way([$nodeid-1,$nodeid],%tags);
#           }
#        }
#     }

   $waylat+=3*$wayspacing;
  }

print_node($waylat-0.5*$wayspacing,$waylon+1.5*$waylength,('osmkey:text' => "tunnel=yes", 'osmkey:align' => 'top'));
print_node($waylat-0.5*$wayspacing,$waylon+3.5*$waylength,('osmkey:text' => "name=Name",  'osmkey:align' => 'top'));
print_node($waylat-0.5*$wayspacing,$waylon+5.5*$waylength,('osmkey:text' => "bridge=yes", 'osmkey:align' => 'top'));
print_node($waylat-0.5*$wayspacing,$waylon+7.5*$waylength,('osmkey:text' => "ref=Ref",    'osmkey:align' => 'top'));


# Parse the file and generate the list

my(%linetags)=parse_txt("lines.txt");

my($primary);

foreach $primary (sort (keys %linetags))
  {
   print_line_types($primary,@{$linetags{$primary}});
  }


# Print some bridges and tunnels on different layers

my($layer);

foreach $layer (-5..5)
  {
   print_node($waylat                       ,$waylon+($layer+ 0)*$wayspacing);
   print_node($waylat+($layer+6)*$wayspacing,$waylon+($layer+ 0)*$wayspacing);
   print_node($waylat+($layer+6)*$wayspacing,$waylon+        18 *$wayspacing);

   print_way([$nodeid-2,$nodeid-1,$nodeid],('highway' => 'primary', 'bridge' => 'yes', 'layer' => $layer));

   print_node($waylat+($layer+6)*$wayspacing,$waylon+9*$waylength+0.5*$wayspacing,('osmkey:text' => "layer=$layer", 'osmkey:align' => 'right'));

   print_node($waylat                        ,$waylon+($layer+12)*$wayspacing);
   print_node($waylat+($layer+18)*$wayspacing,$waylon+($layer+12)*$wayspacing);
   print_node($waylat+($layer+18)*$wayspacing,$waylon+        18 *$wayspacing);

   print_way([$nodeid-2,$nodeid-1,$nodeid],('highway' => 'primary', 'tunnel' => 'yes', 'layer' => $layer));

   print_node($waylat+($layer+18)*$wayspacing,$waylon+9*$waylength+0.5*$wayspacing,('osmkey:text' => "layer=$layer", 'osmkey:align' => 'right'));
  }


#
# Print area types
#

my($areaspacing)=0.005;
my($areaheight)=0.01;
my($areawidth)=0.03;

my($arealat)=$latitude+$areaspacing;
my($arealon)=$longitude+$wayspacing+$areaspacing+12*$waylength;

my($numareas)=0;
my($maxareas)=60;

sub print_area_types
  {
   my($type,@areas)=(@_);

   if(($numareas+$#areas) > $maxareas)
     {
      $arealat=$latitude+$areaspacing;
      $arealon+=$areaspacing+$areawidth;

      $numareas=$#areas;
     }

   my($area);

   foreach $area (@areas)
     {
      print_node($arealat            ,$arealon            );
      print_node($arealat+$areaheight,$arealon            );
      print_node($arealat+$areaheight,$arealon+$areawidth);
      print_node($arealat            ,$arealon+$areawidth);

      my(%tags)=%$area;
      $tags{name}='Name';

      print_way([$nodeid,$nodeid-3,$nodeid-2,$nodeid-1,$nodeid],%tags);

      print_node($arealat-0.3*$areaspacing,$arealon+0.5*$areawidth,('osmkey:text' => $$area{name}, 'osmkey:align' => 'top'));

      $arealat+=$areaspacing+$areaheight;
     }

   $arealat+=2*($areaspacing+$areaheight);
   $numareas+=2+$#areas;
  }


# Parse the file and generate the list

my(%areatags)=parse_txt("areas.txt");

foreach $primary (sort (keys %areatags))
  {
   print_area_types($primary,@{$areatags{$primary}});
  }


#
# Print point types
#

my($pointspacing)=0.005;

my($pointlat)=$latitude+$pointspacing;
my($pointlon)=$arealon+$areaspacing+$areawidth+2*$pointspacing;

my($numpoints)=0;
my($maxpoints)=150;

sub print_point_types
  {
   my($type,@points)=(@_);

   if(($numpoints+$#points) > $maxpoints)
     {
      $pointlat=$latitude+$pointspacing;
      $pointlon+=4*$pointspacing;

      $numpoints=$#points;
     }

   my($point);

   foreach $point (@points)
     {
      my(%tags)=%$point;
      $tags{name}='Name';
      $tags{ele}='ele';         # elevation

      print_node($pointlat,$pointlon,%tags);

      print_node($pointlat-0.3*$pointspacing,$pointlon,('osmkey:text' => $$point{name}, 'osmkey:align' => 'top'));

      $pointlat+=$pointspacing;
     }

   $pointlat+=3*$pointspacing;
   $numpoints+=3+$#points;
  }


# Parse the file and generate the list

my(%pointtags)=parse_txt("points.txt");

foreach $primary (sort (keys %pointtags))
  {
   print_point_types($primary,@{$pointtags{$primary}});
  }


#
# Print a footer
#

print "</osm>\n";
