#![allow(unused)]

use pish::parse::{
    Parse,
    regex::{CompiledPattern, Pattern, bc::BytecodeCompiledRegex},
};

pub fn test_case(_name: &str, script: &[u8], expected_output: &[u8]) {
    use pish::parse::Parse;
    use pish::rw::*;
    use std::io::Read;
    use std::sync::{Arc, Mutex};

    let session = Arc::new(Mutex::new(pish::Session::new_noninteractive()));
    let script = pish::parse::Script::parse_from_bytes(script).unwrap();
    let (stdin, _c1) = InputReader::new(Input::Null);
    let (mut pr, pw) = std::io::pipe().unwrap();
    let (stdout, _c2) = OutputWriter::new(Output::Pipe(pw));
    let mut exec = pish::run::Executor::new(session.clone());
    let mut spawned = exec.execute_script(script, stdin, stdout);
    let _res = spawned.join_timeout(1000);
    let mut actual_output = Vec::new();
    pr.read_to_end(&mut actual_output).unwrap();
    assert_eq!(
        expected_output,
        actual_output,
        "\nexpected: {}\n  actual: {}",
        expected_output.escape_ascii(),
        actual_output.escape_ascii()
    );
}

pub struct MultiTestCompiledPattern {
    dfa: CompiledPattern,
    vm: BytecodeCompiledRegex,
}

impl MultiTestCompiledPattern {
    pub fn matches(&self, string: impl Clone + AsRef<[u8]>) -> bool {
        let dfa_result = self.dfa.matches(string.clone());
        let vm_result = self.vm.matches(string.as_ref());
        assert_eq!(dfa_result, vm_result);
        dfa_result
    }
}

pub fn regex(pat: &str) -> MultiTestCompiledPattern {
    let parsed =
        Pattern::parse_from_bytes(pat.as_bytes()).expect(&format!("pattern {pat} does not parse"));
    let dfa = parsed
        .clone()
        .try_compile()
        .expect(&format!("pattern {pat} does not compile to DFA"));
    let vm = BytecodeCompiledRegex::try_from(parsed.clone())
        .expect(&format!("pattern {pat} does not compile to VM"));
    MultiTestCompiledPattern { dfa, vm }
}
