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
use std::path::PathBuf;
use std::process;

use anyhow::Result;

use crate::core::module::WintsModule;
use crate::core::storage::WintsStorage;
use crate::util::log::{CAUTION, DONE, DRY_RUN, GOTO, INFO, SAD, SEARCH, TRY};

pub struct SearchOptions {
    pub local_basedir: PathBuf,
    pub global_basedir: PathBuf,
    pub module_name: String,
    pub matching_terms: Option<Vec<String>>,
    pub dry_run: bool,
}

pub fn search(options: SearchOptions) -> Result<()> {
    println!(" {} Using module '{}'", INFO, options.module_name);
    if options.dry_run {
        println!(" {} Dry-run mode activated.", DRY_RUN);
    }

    let storage = WintsStorage::load(
        options.local_basedir.clone(),
        options.global_basedir.clone(),
    )?;

    let module = match storage.find_module(options.module_name.clone()) {
        None => maybe_unknown_module(&options),
        Some(module) => module.clone(),
    };

    match options.matching_terms {
        Some(_) => search_urls_based_on_terms(&options, module),
        None => terms_are_mandatory(module),
    }
    Ok(())
}

fn maybe_unknown_module(options: &SearchOptions) -> WintsModule {
    match options.module_name.as_str() {
        "main" => WintsModule::default_module(),
        _ => {
            println!(
                " {} Unknown module '{}'",
                CAUTION,
                options.module_name.clone()
            );
            process::exit(1);
        }
    }
}

fn terms_are_mandatory(module: WintsModule) {
    println!(" {} No terms passed, can't search anything.", CAUTION);

    if let Some(possible_terms) = module.list_of_all_contexts().first() {
        println!(" {} Try with '{}'.", TRY, possible_terms);
    }
}

fn search_urls_based_on_terms(options: &SearchOptions, module: WintsModule) {
    let matching_terms = options.matching_terms.clone().unwrap();

    println!(
        " {} Searching for '{}'...",
        SEARCH,
        matching_terms.join(" ")
    );

    let urls = module.list_of_urls_from_matching_context(matching_terms);
    match urls.is_empty() {
        true => urls_not_found(options, module),
        false => open_urls(options, urls),
    };

    println!(" {} Search completed.", DONE)
}

fn open_urls(options: &SearchOptions, urls: Vec<String>) {
    for url in urls.iter() {
        match options.dry_run {
            true => println!(" {} Open {}", DRY_RUN, url),
            false => match webbrowser::open(url) {
                Ok(_) => println!(" {} Open {}", GOTO, url),
                Err(why) => println!("can't open {} -> {}", url, why),
            },
        };
    }
}

fn urls_not_found(options: &SearchOptions, module: WintsModule) {
    match module.nearest_matching_context(options.matching_terms.clone().unwrap()) {
        Some(nearest_context) => println!(
            " {} Missed, try with terms like in '{}'.",
            SAD, nearest_context
        ),
        None => println!(" {} Nothing found, try with another term.", SAD),
    }
}