#![feature(result_option_inspect)]
#![allow(non_snake_case)]

use std::path::Path;

use codespan_reporting::{
    diagnostic::Label,
    term::{termcolor::StandardStream, Config},
};

use crate::lexer::Spanned;

mod ast;
mod lexer;
mod parser;

//const TEST: &str = include_str!("../assets/why.idl");

fn main() {
    let mut args = std::env::args();
    args.next().unwrap();
    if let Some(file) = args.next() {
        let path = Path::new(&file);
        dbg!(path);
        let codespan_file = codespan_reporting::files::SimpleFile::new(
            &file,
            std::fs::read_to_string(path).unwrap(),
        );
        let writer = StandardStream::stdout(codespan_reporting::term::termcolor::ColorChoice::Auto);
        let config = Config::default();
        match parser::parse(codespan_file.source()) {
            Ok(ast) => println!("SUCCESS: \n{:#?}", ast),
            Err(e) => {
                let msg = e.to_string();
                let label = match e {
                    parser::ParserError::UnexpectedEOF => Label::primary(
                        (),
                        (codespan_file.source().len() - 1)..codespan_file.source().len(),
                    ).with_message("Unexpected end of file here"),
                    parser::ParserError::Unexpected(expected, Spanned(got, span)) => Label::primary((), span.0).with_message(format!("Unexpected `{got}`, expected {expected}")),
                    parser::ParserError::PleaseStopParsingUse => unreachable!()
                };
                let diagnostic = codespan_reporting::diagnostic::Diagnostic::error()
                    .with_message(msg)
                    .with_labels(vec![label]);
                codespan_reporting::term::emit(
                    &mut writer.lock(),
                    &config,
                    &codespan_file,
                    &diagnostic,
                )
                .unwrap();
            }
        }
    }
}

#[macro_export]
macro_rules! unwrap_match {
    ($x:expr, $m:pat => $a:expr) => {
        match $x {
            $m => $a,
            _ => unreachable!(),
        }
    };
}