package Geo::OSM::OsmXML;

use strict;
use warnings;

use Utils::File;
use Utils::Math;
use Utils::Debug;
use XML::Parser;

sub new(){ bless{} }

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

  my $start_time = time();
  my $P = new XML::Parser(Handlers => {Start => \&DoStart, End => \&DoEnd, Char => \&DoChar});
    my $fh = data_open($file_name);
    die "Cannot open OSM File $file_name\n" unless $fh;
    eval {
	$P->parse($fh);
    };
    print "\n" if $DEBUG || $VERBOSE;
    if ( $VERBOSE) {
	printf "Read and parsed $file_name in %.0f sec\n",time()-$start_time;
    }
    if ( $@ ) {
	warn "$@Error while parsing\n $file_name\n";
	return;
    }
    if (not $P) {
	warn "WARNING: Could not parse osm data\n";
	return;
    }

}
sub name(){return($OsmXML::lastName)};

sub bounds(){
  my ($S,$W,$N,$E) = (1e+6,1e+6,-1e+6,-1e+6); # S,W,N,E
  foreach my $Node(values %OsmXML::Nodes){
    $S = $Node->{"lat"} if($Node->{"lat"} < $S);
    $N = $Node->{"lat"} if($Node->{"lat"} > $N);
    $W = $Node->{"lon"} if($Node->{"lon"} < $W);
    $E = $Node->{"lon"} if($Node->{"lon"} > $E);
  }
  return($S,$W,$N,$E);
}

# Function is called whenever an XML tag is started
sub DoStart()
{
  my ($Expat, $Name, %Attr) = @_;
  
  if($Name eq "node"){
    undef %OsmXML::Tags;
    %OsmXML::MainAttr = %Attr;
  }
  if($Name eq "segment"){
    undef %OsmXML::Tags;
    %OsmXML::MainAttr = %Attr;
  }
  if($Name eq "way"){
    undef %OsmXML::Tags;
    undef @OsmXML::WaySegments;
    %OsmXML::MainAttr = %Attr;
  }
  if($Name eq "tag"){
    $OsmXML::Tags{$Attr{"k"}} = $Attr{"v"};
  }
  if($Name eq "seg"){
    push(@OsmXML::WaySegments, $Attr{"id"});
  }
}

# Function is called whenever an XML tag is ended
sub DoEnd(){
  my ($Expat, $Element) = @_;
  if($Element eq "node"){
    my $ID = $OsmXML::MainAttr{"id"};
    $OsmXML::Nodes{$ID}{"lat"} = $OsmXML::MainAttr{"lat"};
    $OsmXML::Nodes{$ID}{"lon"} = $OsmXML::MainAttr{"lon"};
    foreach(keys(%OsmXML::Tags)){
      $OsmXML::Nodes{$ID}{$_} = $OsmXML::Tags{$_};
    }
  }
  if($Element eq "segment"){
    my $ID = $OsmXML::MainAttr{"id"};
    $OsmXML::Segments{$ID}{"from"} = $OsmXML::MainAttr{"from"};
    $OsmXML::Segments{$ID}{"to"} = $OsmXML::MainAttr{"to"};
    foreach(keys(%OsmXML::Tags)){
      $OsmXML::Segments{$ID}{$_} = $OsmXML::Tags{$_};
    }
  }
  if($Element eq "way"){
    my $ID = $OsmXML::MainAttr{"id"};
    $OsmXML::Ways{$ID}{"segments"} = join(",",@OsmXML::WaySegments);
    foreach(keys(%OsmXML::Tags)){
      $OsmXML::Ways{$ID}{$_} = $OsmXML::Tags{$_};
    }    
  }
}

# Function is called whenever text is encountered in the XML file
sub DoChar(){
  my ($Expat, $String) = @_;
}

1;

__END__

=head1 NAME

OsmXML - Module for reading OpenStreetMap XML data files

=head1 SYNOPSIS

  $OSM = new OsmXML();
  $OSM->load("Data/nottingham.osm");
  
  foreach $Way(%OsmXML::Ways){
    @Segments = split(/,/, $Way->{"segments"});
    
    foreach $SegmentID(@Segments){
      $Segment = $OsmXML::Segments{$SegmentID};
    
      $Node1 = $OsmXML::Nodes{$Segment->{"from"}};
      $Node2 = $OsmXML::Nodes{$Segment->{"to"}};
    
      printf "Node at %f,%f, named %s, is a %s",
        $Node2->{"lat"},
        $Node2->{"lon"},
        $Node2->{"name"},
        $Node2->{"highway"};
      }
    }

=head1 AUTHOR

Oliver White (oliver.white@blibbleblobble.co.uk)

=head1 COPYRIGHT

Copyright 2006, Oliver White

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

=cut
