//
// test ownership
fn test0() {
    let a1 = ["s1", "s2"];
    let a2 = a1; //why move didn't happen here?

    println!("iterate a1");
    for i in a1.iter() {
        println!("{}", i);
    }

    // let str1 = String::from("hello");
    // let str2 = str1; //str1 stored on heap, so move happened here but not copy, after move str1 is invalid
    // println!("str1={}", str1) //compile error;
    //
    let str1 = "apple";
    let str2 = str1; //str1 stored on stack not heap, copy happen here but not move, so str1 is still valid
    println!("str1={}", str1)
}

// test slice
fn test1() {
    let mut a = [1, 4, 2, 5, 3];

    // println!("a={}", a); //compile error: std::fmt::Display` is not implemented for `[{integer}; 5]

    let slice = &a[0..2]; //rust slice, [0,2) //[1,4]
    let s2 = &a[..];

    println!("iterate slice");
    for i in slice.iter() {
        //slice.iter() return a tuple for (for .. in ..) syntax
        println!("{}", i);
    }

    println!("iterate s2");
    for i in s2.iter() {
        //slice.iter() return a tuple for (for .. in ..) syntax
        println!("{}", i);
    }

    a.sort();
    println!("after sort, iterate a");
    //cannot borrow `a` as mutable because it is also borrowed as immutable
    // for i in slice.iter() {
    for i in a.iter() {
        //slice.iter() return a tuple for (for .. in ..) syntax
        println!("{}", i);
    }
}

// test tuple
fn test2() {
    struct Color(i32, i32, i32);
    struct Point(i32, i32, i32);

    let black = Color(0xff, 0xfe, 0xfd);
    let origin = Point(0, 0, 0);

    println!("color: {} - {} - {}", black.0, black.1, black.2);

    let tup = (500, 6.4, 1);
    let (x, y, z) = tup;
    println!("x={}, y={}", x, y);

    println!("tup.0={}, tup.1={}", tup.0, tup.1);
    let t2 = tup; //move tup is ok!
    println!("tag2; tup.0={}, tup.1={}", tup.0, tup.1);
}

fn test3() {
    struct Rectangle {
        width: u32,
        height: u32,
    }

    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!("width={}, height={}", rect1.width, rect1.height)
}

//struct member function
struct Circle {
    r: f64,
}

impl Circle {
    fn area(&self) -> f64 {
        return self.r * self.r * std::f64::consts::PI;
    }

    fn len(&self) -> f64 {
        return self.r * 2.0 * std::f64::consts::PI;
    }
}

struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

impl Rectangle {
    fn create_squre(e: u32) -> Rectangle {
        Rectangle {
            width: e,
            height: e,
        }
    }

    fn 
(&self) {
        println!("print self; width={}, height={}", self.width, self.height);
    }
}

fn test4() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!(
        "The area of the rectangle is {} square pixels.",
        rect1.area()
    );

    let c1 = Circle { r: 2.0 };
    println!(
        "the radius of c1={}, the area of c1={}, length of c1={}",
        c1.r,
        c1.area(),
        c1.len()
    );

    let squre_1 = Rectangle::create_squre(5);
    squre_1.print();
}

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}
fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => {
            println!("Lucky penny!");
            1
        }
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}

fn test5() {
    let ret = value_in_cents(Coin::Penny);
    println!("ret={}", ret)
}

fn test6() {
    let v = vec![1, 2, 3];

    v[99]; //out of boundary
}

fn largest(list: &[i32]) -> &i32 {
    let mut largest = &list[0];

    for item in list {
        if item > largest {
            largest = item;
        }
    }

    largest
}

fn test7() {
    let number_list = vec![34, 50, 25, 100, 65];
    let result = largest(&number_list);
    println!("The largest number is {}", result);

    let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8];
    let result = largest(&number_list);
    println!("The largest number is {}", result);
}

fn test8() {
    let r;

    {
        let x = 5;
        r = &x;
    }

    println!("r: {}", r);
}

fn main() {
    println!("main; -enter");

    test8();

    println!("main; -exit");
}

print