extern crate aterm;

use aterm::rc::ATermFactory as Factory;
use aterm::rc::ATerm as FactoryATerm;
use aterm::parse::ATermRead;
use aterm::{ATerm, Term, TermPlaceholder as Placeholder};

use std::fs::File;
use std::io::Read;
use std::io::Result;
use std::process;
use std::rc::Rc;

fn main() {
    if let Some(file) = std::env::args().nth(1) {
        if let Err(e) = exec(file) {
            use std::io::{Write, stderr};
            writeln!(&mut stderr(), "{}", e).unwrap();
            process::exit(1);
        }
    } else {
        println!("Give one argument, a file with an ASCII encoded ATerm. The depth of the tree \
                  will be returned then. ")
    }
}

fn exec(file: String) -> Result<usize> {
    let mut file = File::open(file)?;
    let mut contents = String::new();
    let _ = file.read_to_string(&mut contents);
    let factory: Factory<()> = Factory::new();
    if let Ok((aterm, _)) = factory.read_ascii(&contents) {
        let depth = depth(&aterm);
        println!("{}", depth);
    }
    Ok(0)
}

fn depth(aterm: &Rc<FactoryATerm<()>>) -> usize {
    match aterm.as_inner().term {
        Term::Int(_) | Term::Long(_) | Term::Real(_) | Term::Blob(_) => 1,
        Term::Application(_, ref rec) |
        Term::List(ref rec) => rec.into_iter().map(depth).max().unwrap_or(0) + 1,
        Term::Placeholder(ref p) => {
            match *p {
                Placeholder::Application(ref rec) => {
                    rec.into_iter().map(depth).max().unwrap_or(0) + 1
                }
                _ => 1,
            }
        }
    }
}
