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
133
134
135
136
137
138
139
140
use std::{
    cmp::Ordering,
    collections::{btree_map::Entry, BTreeMap},
    fs,
};

use lightningcss::stylesheet::{PrinterOptions, StyleSheet};

type OneClass = [u8; 5];

pub enum CSSToken {
    Class,
    CustomProperty,
}

#[derive(Default, Clone, PartialEq, Eq)]
pub struct ClassContainer {
    class_name: [ClassIter; 2],
    container: [BTreeMap<String, String>; 2],
}

impl Default for ClassIter {
    fn default() -> Self {
        ClassIter {
            array: [1, 0, 0, 0, 0],
            current_index: 0,
        }
    }
}

impl ClassContainer {
    pub fn add(&mut self, key: String, token: CSSToken) -> Option<String> {
        let index = token as usize;
        if let Some(map) = self.container.get_mut(index) {
            let oldclass = css_to_html(&key);
            match map.entry(oldclass) {
                Entry::Vacant(entry) => {
                    if let Some(new) = self.class_name[index].next() {
                        return Some(entry.insert(new_class(&new)).to_string());
                    }
                }
                Entry::Occupied(entry) => {
                    return Some(entry.get().clone());
                }
            }
        }
        None
    }

    pub fn get(&self, key: String, container: CSSToken) -> Option<String> {
        let index = container as usize;
        if let Some(map) = self.container.get(index) {
            if let Some(v) = map.get(&key) {
                return Some(v.to_string());
            }
        }
        None
    }

    pub fn into_file(&self, stylesheet: StyleSheet) {
        let opt = PrinterOptions {
            minify: true,
            ..Default::default()
        };
        if let Ok(f) = stylesheet.to_css(opt) {
            let _ = fs::write("src/output.css", f.code);
        }
    }
}

#[derive(Clone, PartialEq, Eq)]
pub struct ClassIter {
    array: OneClass,
    current_index: usize,
}

impl ClassIter {}

impl Iterator for ClassIter {
    type Item = OneClass;

    fn next(&mut self) -> Option<Self::Item> {
        let current = self.array;
        self.array[self.current_index] += 1;
        if self.array[self.current_index] == 27 {
            self.array[self.current_index] = 1;
            let mut add_new = true;
            for i in (0..self.current_index).rev() {
                let v = self.array[i];
                match v.cmp(&26) {
                    Ordering::Less => {
                        add_new = false;
                        self.array[i] += 1;
                        self.array[self.current_index] = 1;
                        break;
                    }
                    Ordering::Equal => {
                        self.array[i] = 1;
                    }
                    Ordering::Greater => (),
                }
            }
            if add_new {
                if self.current_index == 4 {
                    return None;
                }

                for i in (0..self.current_index).rev() {
                    self.array[i] = 1;
                }

                self.current_index += 1;
                self.array[self.current_index] = 1;
            }
        }
        Some(current)
    }
}

fn css_to_html(old: &str) -> String {
    if old.starts_with('.') {
        let mut chars = old.chars();
        chars.next();
        chars.as_str().replace('\\', "")
    } else {
        String::from(old)
    }
}

fn new_class(new_class: &OneClass) -> String {
    let mut s = String::new();
    for i in new_class {
        if i == &0 {
            break;
        }
        let c = 96_u8 + i;
        s.push(c as char);
    }
    s
}