use std::{error::Error, fs::File, io::BufReader, path::PathBuf};
use kml_to_fgfp::{self, Airport, EmitterConfig, EventReader};
pub struct Config {
input: PathBuf,
output: PathBuf,
departure: Option<String>,
destination: Option<String>,
}
impl Config {
pub fn build(mut args: impl Iterator<Item = String>) -> Result<Config, Box<dyn Error>> {
args.next();
let input = match args.next() {
Some(path) => PathBuf::from(path),
_ => return Err("Didn't get an input file".into()),
};
let output = match args.next() {
Some(path) => PathBuf::from(path),
_ => return Err("Didn't get a destination directory".into()),
};
let departure = args.next();
let destination = args.next();
Ok(Config {
input,
output,
departure,
destination,
})
}
pub fn print_config() {
eprint!(
"\
Usage:
\x1B[01m{} INPUT OUTPUT [DEPARTURE_AIRPORT] [DESTINATION AIRPORT]\x1B[00m\n
INPUT is the Google Earth (.kml) file.\n
OUTPUT is the name of the generated FlightGear flight plan (.fgfp) file.\n
[DEPARTURE_AIRPORT] is an optional argument detailing the departure airport's
ICAO designation. It would look something like `SAEZ`. You can also type a `/`
to add a specific runway, so it would look like `SAEZ/11`.\n
[DESTINATION_AIRPORT] is an optional argument detailing the destination
airport's ICAO designation. It would look something like `YSSY`. You can also
type a `/` to add a specific runway, so it would look like `YSSY/34L`.\n
Version: {}, {} License
",
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"),
env!("CARGO_PKG_LICENSE")
);
}
}
pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
let mut output_file = File::create(config.output)?;
let mut writer = EmitterConfig::new()
.perform_indent(true)
.indent_string("\t")
.create_writer(&mut output_file);
kml_to_fgfp::write_start_of_tree(&mut writer)?;
let departure = config.departure.map(|ap| airport_decoder(&ap));
let destination = config.destination.map(|ap| airport_decoder(&ap));
kml_to_fgfp::write_airports(&mut writer, &departure, &destination)?;
let input_file = File::open(config.input)?;
let input_file = BufReader::new(input_file);
let parser = EventReader::new(input_file);
kml_to_fgfp::transform_route(parser, &mut writer, &departure, &destination)?;
kml_to_fgfp::close_tree(&mut writer)?;
Ok(())
}
fn airport_decoder(code: &str) -> Airport {
let mut ident = String::from("ICAO");
let mut runway = None;
if code.contains('/') {
let data: Vec<&str> = code.split('/').map(|d| d.trim()).collect();
ident = String::from(data[0]);
runway = Some(String::from(data[1]));
}
Airport { ident, runway }
}