use multilinear::{Condition, EventInfo, InvalidChangeError, MultilinearInfo};

#[test]
fn test_add_event() {
    let mut info = MultilinearInfo::new();
    let channel1 = info.add_channel();
    let channel2 = info.add_channel();

    let condition = vec![
        Condition::new(channel1, 1),
        Condition::change(channel2, 0, 1),
    ];

    let mut event_info = EventInfo::new();
    event_info.add_change(&condition).unwrap();

    let event = info.add_event(event_info);
    assert_eq!(event.0, 0);
}

#[test]
fn test_unrelated_empty() {
    let mut info = MultilinearInfo::new();

    let channel1 = info.add_channel();
    let channel2 = info.add_channel();

    let condition = vec![
        Condition::new(channel1, 1),
        Condition::change(channel2, 0, 1),
    ];

    let mut event_info = EventInfo::new();
    event_info.add_change(&condition).unwrap();
    assert_eq!(
        event_info.add_change(&[]),
        Err(InvalidChangeError::ConflictingConditions)
    );
}

#[test]
fn test_duplicate_channel() {
    let mut info = MultilinearInfo::new();
    let channel = info.add_channel();

    let condition = vec![Condition::new(channel, 0), Condition::new(channel, 0)];

    let mut event_info = EventInfo::new();
    assert_eq!(
        event_info.add_change(&condition),
        Err(InvalidChangeError::DuplicateChannel)
    );
}

#[test]
fn test_overlapping_conditions() {
    let mut info = MultilinearInfo::new();
    let channel = info.add_channel();

    let condition1 = vec![Condition::change(channel, 0, 1)];
    let condition2 = vec![Condition::change(channel, 0, 2)];
    let condition3 = vec![Condition::change(channel, 1, 1)];

    let mut event_info = EventInfo::new();
    event_info.add_change(&condition1).unwrap();
    assert_eq!(
        event_info.add_change(&condition2),
        Err(InvalidChangeError::ConflictingConditions)
    );
    assert_eq!(
        event_info.add_change(&condition3),
        Err(InvalidChangeError::ConflictingConditions)
    );
}

#[test]
fn test_unrelated_conditions() {
    let mut info = MultilinearInfo::new();
    let channel1 = info.add_channel();
    let channel2 = info.add_channel();
    let channel3 = info.add_channel();

    let condition1 = vec![Condition::change(channel1, 0, 1)];
    let condition2 = vec![Condition::change(channel2, 0, 1)];
    let condition3 = vec![Condition::change(channel3, 0, 1)];

    let mut event_info = EventInfo::new();
    event_info.add_change(&condition1).unwrap();
    assert_eq!(
        event_info.add_change(&condition2),
        Err(InvalidChangeError::ConflictingConditions)
    );
    assert_eq!(
        event_info.add_change(&condition3),
        Err(InvalidChangeError::ConflictingConditions)
    );
}

#[test]
fn test_condition_triangle() {
    let mut info = MultilinearInfo::new();
    let channel1 = info.add_channel();
    let channel2 = info.add_channel();
    let channel3 = info.add_channel();

    let condition1 = vec![
        Condition::change(channel1, 0, 1),
        Condition::change(channel2, 0, 1),
    ];
    let condition2 = vec![
        Condition::change(channel2, 0, 1),
        Condition::change(channel3, 0, 1),
    ];
    let condition3 = vec![
        Condition::change(channel3, 0, 1),
        Condition::change(channel1, 0, 1),
    ];

    let mut event_info = EventInfo::new();
    event_info.add_change(&condition1).unwrap();
    assert_eq!(
        event_info.add_change(&condition2),
        Err(InvalidChangeError::ConflictingConditions)
    );
    assert_eq!(
        event_info.add_change(&condition3),
        Err(InvalidChangeError::ConflictingConditions)
    );
}
