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
use std::fs;
use std::fs::{create_dir_all, File};
use std::path::PathBuf;
#[cfg(not(target_family = "wasm"))]
use reqwest::Url;
use anyhow::{anyhow, Result};
use directories::ProjectDirs;

use crate::ir::{ExactDateTime, ExactDate, ExactTime, TimeZoneChoice};
use std::time::SystemTime;
use chrono::Local;
use chrono::{prelude as cr, Datelike, Timelike};

#[cfg(target_family = "wasm")]
use web_sys::{Request, RequestInit, RequestMode, Response};
#[cfg(target_family = "wasm")]
use wasm_bindgen::prelude::*;

#[cfg(not(target_family = "wasm"))]
pub fn download_file(filename:&str, dest:PathBuf, display_name: Option<&str>) -> Result<()>{
    let url = Url::parse(filename)?;
    let name = match display_name {
        Some(name) => name,
        None => filename,
    };
    eprintln!("downloading {}...", name);
    let response = reqwest::blocking::get(url)?;
    if !response.status().is_success() {
        return Err(anyhow!("Cannot download {}: {}", name, response.text()?));
    }
    // write contents of response to dest
    fs::create_dir_all(&dest.parent().unwrap())?;
    File::create(&dest)?;
    fs::write(&dest, response.bytes()?)?;
    println!("downloaded {} to {}", name, &dest.display());
    Ok(())
}

#[cfg(target_family = "wasm")]
pub async fn download_file_wasm(filename: &str, dest: PathBuf, display_name: Option<&str>) -> Result<()> {
    // Create a Request object with the URL of the file to download.

    use wasm_bindgen_futures::JsFuture;
    let request = Request::new_with_str_and_init(
        filename,
        &RequestInit::new()
            .method("GET")
            .mode(RequestMode::Cors)
    ).unwrap();

   let window = web_sys::window().unwrap();
    let resp_value = JsFuture::from(window.fetch_with_request(&request)).await.unwrap();
    assert!(resp_value.is_instance_of::<Response>());
    let resp: Response = resp_value.dyn_into().unwrap();
    let body = resp.body().unwrap().as_string().unwrap();
    fs::write(dest, body)?;
    Ok(())
}

pub enum Dirs{
    Project,
    Data,
    Cache,
    Base,
}

// TODO: update this to match wasm implementation
#[cfg(not(target_family = "wasm"))]
pub fn get_dir() -> Result<PathBuf> {
    if let Some(dir) = ProjectDirs::from("", "", "timeblok") {
        let data_dir = dir.data_dir().join("workalendar");
        create_dir_all(&data_dir)?;
        Ok(data_dir)
    } else {
        Err(anyhow!("Cannot find project directory"))
    }
}

#[cfg(target_family = "wasm")]
pub fn get_dir(dir: Dirs, subdir: Option<&String>) -> Result<PathBuf> {
    use Dirs::*;
    let mut path = match dir {
        Project => PathBuf::from("project"),
        Data => PathBuf::from("data"),
        Cache => PathBuf::from("cache"),
        Base => PathBuf::from("base"),
    };
    if let Some(subdir) = subdir {
        path.push(subdir);
    }
    Ok(path)
}

impl ExactDateTime{
    pub fn from_system_time(base_t: SystemTime) -> Self{
        let base_time: cr::DateTime<Local> = base_t.into();
        Self{
            date: {
                let date = base_time.date_naive();
                ExactDate {
                    year: date.year(),
                    month: date.month(),
                    day: date.day(),
                }
            },
            time: {
                ExactTime {
                    hour: 0,
                    minute: 0,
                    second: 0,
                }
            },
            tz: TimeZoneChoice::Local,
        }
    }
}