// Copyright Rob Gage 2025

use crate::{
    Input,
    Mode,
    ModeResult::{
        self,
        Failure,
        Success,
    },
    Parser,
};


/// A combinator that applies a primary parser, and then an alternate, returning the output from
/// the first of the two to succeed, or the error from the second
pub struct Choice<P1, P2> {
    /// The alternate parser
    pub alternate: P2,
    /// The primary parser
    pub primary: P1,
}

impl<'a, E, I, M, O, P1, P2> Parser<'a, I> for Choice<P1, P2> where
    I: Input<'a>,
    P1: Parser<'a, I, Output = O, Error = E, Message = M>,
    P2: Parser<'a, I, Output = O, Error = E, Message = M>,
{

    type Output = O;

    type Error = E;

    type Message = M;

    fn apply<_Mode: Mode>(&self, input: &'a I) -> ModeResult<O, E, M, _Mode> {
        match self.primary.apply::<_Mode>(input) {
            Success (output, messages) => Success (output, messages),
            Failure (_, _) =>
                match self.alternate.apply::<_Mode>(input) {
                    Success (output, alternate_messages) => Success (output, alternate_messages),
                    Failure (alternate_error, alternate_messages) => Failure (
                        alternate_error,
                        alternate_messages
                    )
                }
        }
    }

}