#!/usr/bin/perl -w
# -*- perl -*-

#
# Author: Slaven Rezic
#
# Copyright (C) 2013,2016,2022,2023,2024,2025 Slaven Rezic. All rights reserved.
# This program is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
# Mail: slaven@rezic.de
# WWW:  http://www.rezic.de/eserte/
#

use strict;
use warnings;

sub usage (;$) {
    my $msg = shift;
    warn $msg, "\n" if $msg;
    die <<EOF;
usage: $0 [-filter-region ...] [-without-notes] files
EOF
}

use Getopt::Long;

my $filter_for_region; # undef/not set: no filter; empty string: filter for Berlin
my $with_notes = 1;
GetOptions
    (
     "filter-region:s" => \$filter_for_region,
     "without-notes" => sub { $with_notes = 0 },
    )
    or usage;
my @infiles = @ARGV
    or usage "bbd file is missing (one or more)";

_add_bbbike_inc();
require Strassen::Core;

binmode STDOUT, 'encoding(utf-8)';

my %id_seen;
my %note_id_seen;
my @errors;
for my $infile (@infiles) {
    Strassen->new_stream($infile)->read_stream
	(sub {
	     my($r, $dir) = @_;
	     for my $osm_watch (@{ $dir->{osm_watch} || [] }) {
		 my($elemtype, $rest) = split /\s+/, $osm_watch, 2;
		 if ($elemtype eq 'note') {
		     if ($with_notes) {
			 my($note_id, $comments) = split /\s+/, $rest;
			 if (exists $note_id_seen{$note_id}) {
			     # consistency check
			     if ($note_id_seen{$note_id} != $comments) {
				 push @errors, "Consistent check failed for note $note_id: $note_id_seen{$note_id} != $comments in file $infile line $.";
			     }
			 } else {
			     my $name = get_name($r, $infile);
			     print join("\t", "note", $note_id, $comments, $name), "\n";
			     $note_id_seen{$note_id} = $comments;
			 }
		     }
		 } else {
		     if ($elemtype !~ m{^(way|node|relation)$}) {
			 push @errors, "Unknown element type '$elemtype' in file $infile line $.";
		     }
		     my($id_assign, $version_assign, $region) = split /\s+/, $rest;
		     if ($id_assign !~ m{^id="\d+"$}) {
			 push @errors, "Expected id assignment, but got '$id_assign' in file $infile line $.";
		     }
		     if ($version_assign !~ m{^version="\d+"$}) {
			 push @errors, "Expected version assignment, but got '$version_assign' in file $infile line $.";
		     }
		     $region = '' if !defined $region;
		     if (!defined $filter_for_region || $filter_for_region eq $region) {
			 my $key = "$elemtype-$id_assign";
			 if (exists $id_seen{$key}) {
			     # consistency check
			     if ($id_seen{$key} ne $version_assign) {
				 push @errors, "Version mismatch for <$elemtype $id_assign>: $id_seen{$key} ne $version_assign in file $infile line $.";
			     }
			 } else {
			     my $name = get_name($r, $infile);
			     print join("\t", $elemtype, $id_assign, $version_assign, $name), "\n";
			     $id_seen{$key} = $version_assign;
			 }
		     }
		 }
	     }
	 });
}

if (@errors) {
    die join("\n", @errors), "\n";
}

sub _add_bbbike_inc {
    require lib;
    require FindBin;
    lib->import("$FindBin::RealBin/..", "$FindBin::RealBin/../lib");
    lib->import("/home/e/eserte/src/bbbike", "/home/e/eserte/src/bbbike/lib");
}

{
    my $crossings;
    sub _get_crossings {
	if (!$crossings) {
	    require Strassen::Core;
	    require Strassen::Kreuzungen;
	    require Strassen::MultiStrassen;
	    require Strassen::StrassenNetz;
	    my $ms = MultiStrassen->new(qw(strassen landstrassen landstrassen2));
	    my $str_net = StrassenNetz->new($ms);
	    $str_net->make_net(UseCache => 1);
	    $crossings = Kreuzungen->new(UseCache => 1, Strassen => $ms, WantPos => 1);
	}
	$crossings;
    }
}

sub get_crossing {
    my($coord) = @_;
    _get_crossings()->get_crossing_name($coord);
}

sub get_nearest_crossing {
    my($coord) = @_;
    my($x,$y) = split /,/, $coord;
    my $nearest_info = _get_crossings()->nearest($x,$y, IncludeDistance => 1, BestOnly => 1);
    if ($nearest_info) {
	my($xy, $dist) = @$nearest_info;
	if ($dist <= 100) {
	    return get_crossing($xy);
	}
    }
    undef;
}

sub get_name {
    my($r, $filename) = @_;
    my $name = $r->[Strassen::NAME()];
    if (!$name) {
	my @result_words;
	my $c = $r->[Strassen::COORDS()];
	if (@$c == 1) {
	    my $crossing = get_crossing($c->[0]);
	    if (!$crossing) {
		$crossing = get_nearest_crossing($c->[0]);
		if ($crossing) {
		    @result_words = ('nahe');
		}
	    }
	    if ($crossing) {
		if ($filename =~ /ampeln/) {
		    if ($r->[Strassen::CAT()] =~ /^B/) {
			unshift @result_words, 'Bahnuebergang'; # XXX welches Encoding hat die erzeugte Datei?
		    } else {
			unshift @result_words, 'Ampel';
		    }
		}
		push @result_words, $crossing;
	    }
	}
	if (@result_words) {
	    $name = join ' ', @result_words;
	}
    }
    $name;
}
