
fn main() {
    println!("Hello, world!");
    looping_through_a_list_with_rev();
}

// rust has 3 types of loops: loop, while and for

// This will not stop until interrupted unless told by a return, break or a ctrl-c
fn forever_loop () {
    loop {
        println!("another loop!")
    }

    let mut counter = 0;
    let value_from_loop = loop {
        counter += 1;
        if counter == 4 {
            break counter;
        }
    };
}

// continue
// this will start the loop over again from the top regardless of the code after it
// break, can return values from a loop, needs a ; after break to do that
    
// one use of a loop is checking weather a thread is finished or do a operation that you know might fail

fn loop_with_labels () {
    let mut counter = 0;
    let result = 'first_loop: loop {
        println!("counter = {counter}");
        let mut remaining = 10;
        'inner_loop: loop {
            println!("remaining = {remaining}");
            if remaining == 9 {
                // both acceptable
                break 'inner_loop;
                // continue 'inner_loop;
            }
            if counter == 2 {
                // returns a value and goes out of the outermost loop called/labelled first_loop
                break 'first_loop counter*2;
            }
            remaining -= 1;
        }
        counter += 1;
    };
    println!("counter = {counter}");
    println!("result = {result}");
}

fn looping_with_while () {
    let mut count_down = 3;
    println!("liftoff in {count_down} seconds");

    while count_down != 0 {
        println!("{}!", count_down);

        count_down -= 1;
    }

    println!("Lift-Off!");

}

// while will only run when the condition/bool is true otherwise it will call a break of the loop by itself
// removes a lot of the nesting of if, else, and break statements in loops

fn looping_through_a_list () {
    let a = [32, 5, 20, 40, 50, 60];
    let mut index = 0;
    // if a.len was a static number this would/could cause the program to panic 
    // because if a was modified and the static number was not then it would attempt to go out out the assigned memory
    // compiler will add code to check if static number is within the bounds and therefore is slower
    // using list.len() is always a better solution
    while index < a.len() {
        println!("the value is: {}", a[index]);
        index += 1;
    }
}

// for loops are the most safe and easy to use

fn looping_through_a_list_more_concise_and_secure () {
    let b = [32, 5, 6, 79, 88, 99];
    // is is more safe and is faster than even a.len() no operation for checking the size everytime/re-eval the bool
    // removed chance of bug in static number and is faster
    for element in b {
        println!("the value is {}", element);
    }
    // Ranges are start..end not Range(5), that range method/funct is fake
    for num in 0..5 {
        println!("the value is now: {}", num);
    }


}


fn looping_through_a_list_with_rev () {
    // this reverse the order of a range
    for number in (1..4).rev() {
        println!("{}!", number);
    }
    println!("Lift-Off!!");
}
