use std::{error::Error, io::Write};
use xml::writer::EventWriter;
use super::Airport;
pub struct Waypoint {
pub number: usize,
pub ident: String,
pub lon: f64,
pub lat: f64,
pub altitude: usize,
}
pub enum LookingFor {
OpeningPlacemark,
OpeningName,
ContentName,
ClosingName,
OpeningStyleUrl,
ContentStyleUrl,
ClosingStyleUrl,
OpeningCoordinates,
ContentCoordinates,
ClosingCoordinates,
ClosingPlacemark,
}
pub fn handle_start_event(
mut waypoint: Waypoint,
mut current_search: LookingFor,
mut drop: bool,
wp: usize,
name: &str,
) -> (Waypoint, LookingFor, bool) {
if matches!(current_search, LookingFor::OpeningPlacemark) && name == "Placemark" {
waypoint.number = wp;
current_search = LookingFor::OpeningName;
drop = false;
}
if matches!(current_search, LookingFor::OpeningName) && name == "name" {
current_search = LookingFor::ContentName;
}
if matches!(current_search, LookingFor::OpeningStyleUrl) && name == "styleUrl" {
current_search = LookingFor::ContentStyleUrl;
}
if matches!(current_search, LookingFor::OpeningCoordinates) && name == "coordinates" {
current_search = LookingFor::ContentCoordinates;
}
(waypoint, current_search, drop)
}
pub fn handle_characters_event(
mut waypoint: Waypoint,
mut current_search: LookingFor,
mut drop: bool,
line: String,
departure_airport: &Option<Airport>,
destination_airport: &Option<Airport>,
) -> (Waypoint, LookingFor, bool) {
if matches!(current_search, LookingFor::ContentName) {
waypoint.ident = String::from(&line);
current_search = LookingFor::ClosingName;
if let Some(airport) = departure_airport {
if line == airport.ident {
current_search = LookingFor::ClosingPlacemark;
drop = true;
}
}
if let Some(airport) = destination_airport {
if line == airport.ident {
current_search = LookingFor::ClosingPlacemark;
drop = true;
}
}
}
if matches!(current_search, LookingFor::ContentStyleUrl) {
if line != "#FixMark" {
drop = true;
current_search = LookingFor::ClosingPlacemark;
return (waypoint, current_search, drop);
}
current_search = LookingFor::ClosingStyleUrl;
}
if matches!(current_search, LookingFor::ContentCoordinates) {
let data: Vec<&str> = line.split(',').map(|l| l.trim()).collect();
let mut message = String::new();
waypoint.lon = match data[0].parse() {
Ok(d) => d,
Err(e) => {
message = e.to_string();
0f64
}
};
waypoint.lat = match data[1].parse() {
Ok(d) => d,
Err(e) => {
message = e.to_string();
0f64
}
};
waypoint.altitude = match data[2].parse() {
Ok(d) => d,
Err(e) => {
message = e.to_string();
0usize
}
};
if !message.is_empty() {
eprintln!(
"\x1B[01;33mDropping\x1B[00;01m {}\x1B[00m waypoint: {}",
waypoint.ident, message
);
drop = true;
}
current_search = LookingFor::ClosingCoordinates;
}
(waypoint, current_search, drop)
}
pub fn handle_end_event<W: Write>(
writer: &mut EventWriter<W>,
waypoint: Waypoint,
mut current_search: LookingFor,
drop: bool,
mut wp: usize,
name: &str,
) -> Result<(Waypoint, LookingFor, usize), Box<dyn Error>> {
if matches!(current_search, LookingFor::ClosingName) && name == "name" {
current_search = LookingFor::OpeningStyleUrl;
}
if matches!(current_search, LookingFor::ClosingStyleUrl) && name == "styleUrl" {
current_search = LookingFor::OpeningCoordinates;
}
if matches!(current_search, LookingFor::ClosingCoordinates) && name == "coordinates" {
current_search = LookingFor::ClosingPlacemark;
}
if matches!(current_search, LookingFor::ClosingPlacemark) && name == "Placemark" {
if !drop {
super::write_waypoint(writer, &waypoint)?;
wp += 1;
}
current_search = LookingFor::OpeningPlacemark;
}
Ok((waypoint, current_search, wp))
}