use ferris_says::say;
use std::io::{stdout, BufWriter};
use std::collections::HashMap;
use std::fs::File;

fn main() {
    ferris();

    // RUST 基础语法
    let mut a = 123; //不可变变量 mut修饰的变量是允许改变的 (mutable 可变的)
    println!("{}",a);

    a = 456;
    println!("{}",a);

    // RUST 的基本数据类型
    // 在计算机中,有符号数是可以用来区分数值的正负。而无符号数仅有正值,没有负值。
    // 整数类型 u8,u16,u32,u64,u128,usize | i8,i16,i32,i64,i128,isize
    // 浮点型 f32,f64
    // 布尔型 bool -> true | false
    // 字符型 char utf-8
    // 复合类型 元组

    let _i: u8 = 123;
    let _f: f32 = 1.5;
    let _b: bool = true; //默认值是false
    let _t: (u8,f32,bool) = (_i,_f,_b);

    //数组与元组区别 [类型,数量]
    let _a: [u8;2] = [_i,_i];
    println!("{:?}",_a);

    //bool 的默认值
    let __b: bool = Default::default();
    println!("{:?}",__b);

    // vec 变长数组
    let _v: Vec = (0..10).collect();
    println!("{:?}",_v);

    // Map k-v 存、取值
    let mut _h: HashMap = HashMap::new();
    _h.insert(0,2.5);
    _h.insert(1,3.5);
    println!("{:?}",_h);

    //Struct
    #[derive(Debug)]
    struct First{
        _one: String,
        _two: u8,
        _three: bool
    }

    let _fv = First{
        _one: String::from("first is _one"),
        _two: 12,
        _three: true
    };

    println!("{:?}",_fv);

    //Enum 枚举
    #[derive(Debug)]
    enum Two{
        TwoOne, TwoZero
    }

    let _et: Two = Two::TwoOne;
    println!("{:?}",_et);

    //string
    let _s = "Hello";
    let _s1 = "OK"; // &str 不可变的固定长度字符串
    println!("{:?}",_s.len());

    let mut _s2 = String::from("Hello Rust"); //可变的,在堆上分配的UTF-8的字节缓冲区
    println!("{:?}",_s2.len());

    _s2.push_str("hei,");
    println!("{:?}",_s2.len());

    // 流程语句 if else
    let number = 3;
    if number < 5{
        println!("was true")
    }else{
        println!("was false")
    }

    // match 匹配
    let some_u8_value = 1u8;
    match some_u8_value {
        1 => println!("one"),
        3 => println!("three"),
        5 => println!("five"),
        7 => println!("seven"),
        _ => println!("default"),
    }

    // loop 循环
    // println!("forever")
    // loop{
    //     println!("and ever")
    // }

    // for 循环,在指定条件下有限
    for number in (1..4).rev(){
        println!("{}!",number);
    }
    println!("LIFTOFF!!!");

    // 错误处理 可恢复错误和不可恢复错误
    // Option
    let _o: Option = checked(0,1);
    match _o {
        None => println!("_o match None"),
        Some(_ov) => println!("_o match Some {}",_ov),
    }

    //Result //可恢复错误
    // enum Result{
    //     Ok(T),
    //     Err(E)
    // }

    let _file = File::open("D:/www/rust/hello-rust/hello.txt");
    match _file {
        Ok(file) => {
            println!("_file match ok");
        },
        Err(err) => {
            println!("_file match err");
        }
    }

    //panic! 不可恢复错误
    println!("error!!!");


}

pub fn checked(d1: u32, d2: u32) -> Option{
    if d2 == 0{
        None
    }else{
        Some(d1 / d2)
    }
}

pub fn ferris(){
    let stdout = stdout();
    let message = String::from("Hello fellow Rustaceans!");
    let width = message.chars().count();

    let mut writer = BufWriter::new(stdout.lock());
    say(message.as_bytes(),width,&mut writer).unwrap();
}