1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use chrono::prelude::*;
use fs2::FileExt;

use std::fs::{OpenOptions};
use std::io::{BufReader, BufRead, Write, Seek, SeekFrom};
use std::env;
pub fn log(s: &str) {
    let path = std::env::current_exe().unwrap();
    let filename = std::path::Path::new(&path).file_name().unwrap().to_str().unwrap();

    let home_dir = get_home_dir().unwrap_or_else(|| String::from("."));
    let path;
    if cfg!(target_os = "windows") {
        path = format!("{}/AppData/Local/Wei/{}.log.txt", home_dir, filename);
    } else {
        path = format!("{}/.wei/{}.log.txt", home_dir, filename);
    }

    if !std::path::Path::new(&path).exists() {
        std::fs::create_dir_all(std::path::Path::new(&path).parent().unwrap()).unwrap();
    }

    let local: DateTime<Local> = Local::now();
    let data = format!("{} {}",local.format("%Y-%m-%d %H:%M"), s);

    #[cfg(target_os = "windows")] 
    write_and_prune_file(&path, &data, 100).unwrap();

    #[cfg(not(target_os = "windows"))] {
        let mut file = OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap();
        let reader = BufReader::new(&file);
        let mut lines: Vec<String> = reader.lines().collect::<Result<_, _>>().unwrap();
        lines.push(data);
        if lines.len() > 100 {
            lines.remove(0);
        }
        file.seek(SeekFrom::Start(0)).unwrap();
        file.set_len(0).unwrap();  // Truncate the file
        let mut writer = std::io::BufWriter::new(&file);
        for line in &lines {
            writeln!(writer, "{}", line).unwrap();
        }
    }
}

#[macro_export]
macro_rules! info {
    ($($arg:tt)*) => {{
        let message = format!($($arg)*);
        crate::wei_log::log(&message); // 将格式化后的字符串传递给函数
        // println!("{}", message);
    }}
}

#[macro_export]
macro_rules! error {
    ($($arg:tt)*) => {{
        let message = format!($($arg)*);
        let message = format!("错误: {}", message);
        crate::wei_log::log(&message); // 将格式化后的字符串传递给函数
        // println!("{}", message);
    }}
}

#[macro_export]
macro_rules! info_println {
    ($($arg:tt)*) => {{
        let message = format!($($arg)*);
        crate::wei_log::log(&message); // 将格式化后的字符串传递给函数
        // println!("{}", message);
    }}
}

#[macro_export]
macro_rules! info_print {
    ($($arg:tt)*) => {{
        let message = format!($($arg)*);
        crate::wei_log::log(&message); // 将格式化后的字符串传递给函数
        // print!("{}", message);
    }}
}


fn get_home_dir() -> Option<String> {
    if cfg!(target_os = "windows") {
        env::var("USERPROFILE").ok()
    } else {
        env::var("HOME").ok()
    }
}

fn write_and_prune_file(path: &str, content: &str, max_lines: usize) -> std::io::Result<()> {
    let mut file = OpenOptions::new().read(true).write(true).create(true).open(path)?;

    file.lock_exclusive()?;

    // Step 1: Read all lines
    let reader = BufReader::new(&file);
    let mut lines: Vec<String> = reader.lines().collect::<Result<_, _>>()?;

    // Step 2: Prune lines if necessary
    if lines.len() >= max_lines {
        lines.remove(lines.len() - 1);
    }

    // Step 3: Insert new line at the top
    lines.insert(0, content.to_string());

    // Step 4: Seek to the start of the file and write all lines
    file.seek(SeekFrom::Start(0))?;
    file.set_len(0)?;  // Truncate the file
    for line in &lines {
        writeln!(file, "{}", line)?;
    }

    file.unlock()?;

    Ok(())
}



// #[cfg(test)]
// mod tests {
//     use super::*;

//     #[test]
//     fn it_works() {
//         let result = add(2, 2);
//         assert_eq!(result, 4);
//     }
// }