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
use std::str::FromStr;

use itertools::Itertools;

use xcell_errors::Validation;
use xcell_types::{EnumerateDescription, IntegerKind, StringDescription, TypeMetaInfo};

use crate::{utils::first_not_nil, CalamineTable, Success, WorkspaceManager, XCellHeader, XTable};

use super::*;

pub use self::class::XClassItem;

mod class;
mod dictionary;
mod enumerate;

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum XTableKind {
    Array(Box<XArrayTable>),
    Dictionary(Box<XDictionaryTable>),
    Enumerate(Box<XEnumerateTable>),
    Class(Box<XClassTable>),
}

impl Default for XTableKind {
    fn default() -> Self {
        Self::Array(Default::default())
    }
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct XArrayTable {
    pub headers: Vec<XCellHeader>,
    pub data: Vec<XDataItem>,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct XDictionaryTable {
    pub headers: Vec<XCellHeader>,
    pub data: Vec<XDataItem>,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct XEnumerateTable {
    /// 0 表示未设置
    pub id_column: usize,
    pub id_type: IntegerKind,
    pub comment_column: usize,
    pub headers: Vec<XCellHeader>,
    pub data: BTreeMap<String, XDataItem>,
}

/// 生成一个类, 适用于全局配置
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct XClassTable {
    pub items: Vec<XClassItem>,
    pub data: Vec<XCellValue>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct XDataItem {
    pub id: BigInt,
    pub name: String,
    pub comment: String,
    pub data: Vec<XCellValue>,
}

impl XTableKind {
    pub fn read_table_data(&mut self, table: &CalamineTable, path: &Path, meta: &TypeMetaInfo) {
        match self {
            XTableKind::Array(v) => v.read_table_data(table, path),
            XTableKind::Enumerate(v) => v.read_table_data(table, path),
            XTableKind::Class(v) => v.read_table_data(table, path, meta),
            XTableKind::Dictionary(_) => {
                todo!()
            }
        }
    }
}

impl XTableKind {
    pub fn key_field(&self) -> String {
        self.key_item().map(|v| v.field_name.as_str()).unwrap_or("id").to_string()
    }
    pub fn key_type(&self) -> XCellTyped {
        self.key_item().map(|v| v.typing.clone()).unwrap_or_else(|| StringDescription::default().into())
    }
    fn key_item(&self) -> Option<&XCellHeader> {
        match self {
            XTableKind::Array(v) => v.headers.get(0),
            XTableKind::Enumerate(v) => v.headers.get(0),
            XTableKind::Class(_) => None,
            XTableKind::Dictionary(_) => {
                todo!()
            }
        }
    }
    pub fn rows(&self) -> Vec<&XDataItem> {
        match self {
            XTableKind::Array(v) => v.data.iter().collect(),
            XTableKind::Enumerate(v) => v.data.values().collect(),
            XTableKind::Class(_) => vec![],
            XTableKind::Dictionary(_) => {
                todo!()
            }
        }
    }
    pub fn headers(&self) -> Vec<&XCellHeader> {
        match self {
            XTableKind::Array(v) => v.headers.iter().collect(),
            XTableKind::Enumerate(v) => v.headers.iter().collect(),
            XTableKind::Class(_) => {
                vec![]
            }
            XTableKind::Dictionary(_) => {
                todo!()
            }
        }
    }
    pub fn rows_count(&self) -> usize {
        match self {
            XTableKind::Array(v) => v.data.len(),
            XTableKind::Enumerate(v) => v.data.len(),
            XTableKind::Class(v) => v.items.len(),
            XTableKind::Dictionary(_) => {
                todo!()
            }
        }
    }
}