use nexus_lang::Location;
use pretty_assertions::assert_eq;

#[test]
fn new() {
    let mut l = Location::new(0, 1, 1);

    assert_eq!(l, Location::default());

    assert_eq!(l.index, 0);
    assert_eq!(l.line, 1);
    assert_eq!(l.column, 1);

    for i in 2..11 {
        l.next_column();

        assert_eq!(l.index, i - 1);
        assert_eq!(l.line, 1);
        assert_eq!(l.column, i);
    }

    for i in 2..11 {
        l.newline();

        assert_eq!(l.index, i + 8);
        assert_eq!(l.line, i);
        assert_eq!(l.column, 1);
    }
}

#[test]
fn from_string() {
    assert_eq!(
        Location::from_string("Hi\nThere\n!!!"),
        Location::new(12, 3, 3)
    );
}

#[test]
fn newline() {
    let mut l = Location::new(12, 3, 3);

    assert_eq!(l.index, 12);
    assert_eq!(l.line, 3);
    assert_eq!(l.column, 3);

    l.newline();

    assert_eq!(l.index, 13);
    assert_eq!(l.line, 4);
    assert_eq!(l.column, 1);
}

#[test]
fn next_column() {
    let mut l = Location::new(12, 3, 3);

    assert_eq!(l.index, 12);
    assert_eq!(l.line, 3);
    assert_eq!(l.column, 3);

    l.next_column();

    assert_eq!(l.index, 13);
    assert_eq!(l.line, 3);
    assert_eq!(l.column, 4);
}

#[test]
fn as_source_offset() {
    let s = "Hi\nThere\n!!!";
    let p = Location::new(11, 3, 3);

    assert_eq!(p.index, p.as_source_offset(s).offset());

    // Unicode test.
    assert_eq!(
        Location::new(0, 1, 5).as_source_offset("ŮñĭçøƋɇ").offset(),
        8
    );

    // Out-of-range validation (points at last byte).
    assert_eq!(Location::new(0, 10, 10).as_source_offset(s).offset(), 12);
}

#[test]
fn with_column_offset() {
    let l = Location::new(12, 3, 3);
    let l2 = l.with_column_offset(2);

    assert_eq!(l2.index, 12);
    assert_eq!(l2.line, 3);
    assert_eq!(l2.column, 5);
}
