1use std::fs::{self, File};
2use std::io::{ErrorKind, Write};
3
4use chrono::{DateTime, FixedOffset, Local};
5
6use crate::utils;
7
8#[derive(Debug)]
9pub enum SessionStatus {
10 Started(DateTime<FixedOffset>),
11 NotStarted,
12}
13
14#[derive(Debug)]
15pub struct Session<'a> {
16 started_at: Option<DateTime<FixedOffset>>,
17 ended_at: Option<DateTime<FixedOffset>>,
18 session_dir: &'a str,
19 session_path: String,
20 pub status: SessionStatus,
21 session_name: &'a str,
22}
23
24impl Session<'_> {
25 pub fn new<'a>(session_dir: &'a str, session_name: &'a str) -> Session<'a> {
26 let session_path = format!("{}/{}", session_dir, session_name);
27 let status = Session::get_status(&session_path);
28 let started_at = match status {
29 SessionStatus::Started(secs) => Some(secs),
30 SessionStatus::NotStarted => None,
31 };
32
33 Session {
34 started_at,
35 ended_at: None,
36 session_dir,
37 status,
38 session_path,
39 session_name,
40 }
41 }
42
43 fn get_status(path: &str) -> SessionStatus {
48 match fs::metadata(&path) {
49 Ok(metadata) => SessionStatus::Started(utils::get_metadata_created(metadata)),
50 Err(e) => {
51 if e.kind() == ErrorKind::NotFound {
52 SessionStatus::NotStarted
53 } else {
54 panic!("error getting session metadata: {}", e);
55 }
56 }
57 }
58 }
59
60 pub fn start(&self) -> DateTime<FixedOffset> {
62 if let SessionStatus::Started(_) = self.status {
63 panic!("Tried to start a session that is already started.");
64 }
65
66 match File::create(&self.session_path) {
67 Ok(file) => match file.metadata() {
68 Ok(metadata) => utils::get_metadata_created(metadata),
69 Err(e) => panic!("error getting session start time: {}", e),
70 },
71 Err(e) => panic!("error creating session file: {}", e),
72 }
73 }
74
75 pub fn end(&mut self) -> DateTime<FixedOffset> {
77 if let SessionStatus::NotStarted = self.status {
78 panic!("Tried to end a session that hasn't been started.");
79 }
80
81 if let Err(e) = fs::remove_file(&self.session_path) {
83 panic!("error removing session file: {}", e);
84 }
85
86 let ended_at = utils::local_to_fixed_offset(Local::now());
87
88 self.ended_at = Some(ended_at.clone());
90 ended_at
91 }
92
93 pub fn record(&self, log_name: &str) {
96 let log_file_path = format!("{}/{}", self.session_dir, log_name);
97 let mut file = utils::create_or_open_file(&log_file_path);
98
99 let start = self.started_at.unwrap();
100 let end = self.ended_at.unwrap();
101
102 let start_dt = utils::format_datetime(&start);
103 let end_dt = utils::format_datetime(&end);
104 let session_record = format!("{},{}\n", &start_dt, &end_dt);
105
106 file.write(&session_record.as_bytes()).unwrap_or_else(|e| {
107 let session_info = format!("start,end,length\n{}", &session_record);
108 panic!("Error logging session:\n{}\nerror: {}", &session_info, e);
109 });
110 }
111}