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
use soulog::*;
use lazy_db::*;
use crate::{list, archive::Archive};

pub fn younger(this: &[u16; 3], other: &[u16; 3]) -> bool {
    let this_date = this[2] as u32 * 10000 + this[1] as u32 * 100 + this[0] as u32;
    let other_date = other[2] as u32 * 10000 + other[1] as u32 * 100 + other[0] as u32;
    this_date > other_date
}

pub fn sort(mut logger: impl Logger) {
    // load archive
    let archive = Archive::load(logger.hollow());

    let unsorted = list::read(
        |x| x.collect_string(),
        &if_err!((logger) [Sort, err => ("While reading unsorted stack length: {err:?}")] retry search_database!((archive.database()) /order/unsorted)),
        logger.hollow(),
    );

    if unsorted.len() == 0 {
        log!((logger.verbose) Sort("No unsorted items on unsorted stack; doing nothing") as Inconvenience);
        return;
    }

    let mut sorted = list::read(
        |x| x.collect_string(),
        &if_err!((logger) [Sort, err => ("While reading sorted list length: {err:?}")] retry search_database!((archive.database()) /order/sorted)),
        logger.hollow(),
    ).into_vec();

    log!((logger) Sort("Sorting unsorted entries..."));
    // main sorting code
    for usort_uid in unsorted.into_vec() {
        let usort_date = *archive.get_entry(usort_uid.clone(), logger.hollow()).unwrap().date(logger.hollow());
        
        sorted.retain(|item| item != &usort_uid); // remove duplicates

        let mut is_oldest = true;
        for i in (0..sorted.len()).rev() {
            let sort_date = *archive.get_entry(sorted[i].clone(), logger.hollow()).unwrap().date(logger.hollow());

            if younger(&usort_date, &sort_date) {
                sorted.insert(i + 1, usort_uid.clone()); // replace the one before
                is_oldest = false;
                break;
            }
        } if is_oldest {
            sorted.insert(0, usort_uid);
        }
    }

    // Store updates
    log!((logger) Sort("Sorted list length: {}", sorted.len()));
    list::write( // store newly sorted list
        sorted.as_ref(),
        |file, x| LazyData::new_string(file, x),
        &if_err!((logger) [Sort, err => ("While initing sorted list: {err:?}")] retry search_database!((archive.database()) /order/sorted)),
        logger.hollow(),
    );

    list::write(
        &[],
        |file, x: &String| LazyData::new_string(file, x),
        &if_err!((logger) [Sort, err => ("While initing unsorted list: {err:?}")] retry search_database!((archive.database()) /order/unsorted)),
        logger.hollow()
    );

    log!((logger.vital) Sort("Successfully sorted entries") as Log);
}

pub fn sort_uids(uids: &[String], logger: impl Logger) -> Box<[String]> {
    // load archive & sort if sorting is needed
    let archive = Archive::load(logger.hollow());
    sort(logger.hollow());

    let sorted = read_sorted(&archive, logger.hollow()).into_vec();
    
    // remove unspecified
    sorted.into_iter().filter(|x| uids.contains(x)).collect()
}

pub fn read_sorted(archive: &Archive, mut logger: impl Logger) -> Box<[String]> {
    list::read(
        |x| x.collect_string(),
        &if_err!((logger) [Sort, err => ("While reading sorted list: {err:?}")] retry search_database!((archive.database()) /order/sorted)),
        logger.hollow(),
    )
}