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
141
142
143
144
145
146
147
148
149
150
151
use {
	crate::{Cast, CastWithRules, Convert, Result, Value, ValueError},
	chrono::NaiveDateTime,
	uuid::Uuid,
};

macro_rules! expect_arguments {
	($arguments: expr, $expect: expr) => {
		match $arguments.len() {
			$expect => (),
			found => {
				return Err(ValueError::NumberOfFunctionParamsNotMatching {
					expected: $expect,
					found,
				}
				.into())
			}
		}
	};
}

macro_rules! optional_expect_arguments {
	($arguments: expr, $min: expr, $max: expr) => {
		match $arguments.len() {
			len if ($min..=$max).contains(&len) => (),
			found => {
				return Err(ValueError::NumberOfFunctionParamsNotMatching {
					expected: $min,
					found,
				}
				.into())
			}
		}
	};
}

impl Value {
	pub fn function_if_null(mut arguments: Vec<Self>) -> Result<Self> {
		expect_arguments!(arguments, 2);
		Ok(arguments.remove(0).if_null(arguments.remove(0)))
	}
	pub fn function_null_if(mut arguments: Vec<Self>) -> Result<Self> {
		expect_arguments!(arguments, 2);
		arguments.remove(0).null_if(arguments.remove(0))
	}
	pub fn function_iif(mut arguments: Vec<Self>) -> Result<Self> {
		expect_arguments!(arguments, 3);
		arguments
			.remove(0)
			.iif(arguments.remove(0), arguments.remove(0))
	}
	pub fn function_to_lowercase(mut arguments: Vec<Self>) -> Result<Self> {
		expect_arguments!(arguments, 1);
		arguments.remove(0).to_lowercase()
	}
	pub fn function_to_uppercase(mut arguments: Vec<Self>) -> Result<Self> {
		expect_arguments!(arguments, 1);
		arguments.remove(0).to_uppercase()
	}
	pub fn function_left(mut arguments: Vec<Self>) -> Result<Self> {
		expect_arguments!(arguments, 2);
		arguments.remove(0).left(arguments.remove(0))
	}
	pub fn function_right(mut arguments: Vec<Self>) -> Result<Self> {
		expect_arguments!(arguments, 2);
		arguments.remove(0).right(arguments.remove(0))
	}
	pub fn function_length(mut arguments: Vec<Self>) -> Result<Self> {
		expect_arguments!(arguments, 1);
		arguments.remove(0).length()
	}

	pub fn function_concat(mut arguments: Vec<Self>) -> Result<Self> {
		arguments.remove(0).concat(arguments)
	}

	pub fn function_replace(mut arguments: Vec<Self>) -> Result<Self> {
		expect_arguments!(arguments, 3);
		arguments
			.remove(0)
			.replace(arguments.remove(0), arguments.remove(0))
	}

	pub fn function_round(mut arguments: Vec<Self>) -> Result<Self> {
		optional_expect_arguments!(arguments, 1, 2);
		let value = arguments.remove(0);
		let places = if !arguments.is_empty() {
			arguments.remove(0)
		} else {
			Self::I64(0)
		};
		value.round(places)
	}

	pub fn function_rand(arguments: Vec<Self>) -> Result<Self> {
		match arguments.len() {
			0 => Self::function_random_float(arguments),
			2 => Self::function_random_int(arguments),
			found => {
				Err(ValueError::NumberOfFunctionParamsNotMatching { expected: 0, found }.into())
			}
		}
	}
	pub fn function_random_float(arguments: Vec<Self>) -> Result<Self> {
		expect_arguments!(arguments, 0);
		Ok(Self::F64(fastrand::f64()))
	}
	pub fn function_random_int(mut arguments: Vec<Self>) -> Result<Self> {
		expect_arguments!(arguments, 2);
		let min: i64 = arguments.remove(0).cast()?;
		let max: i64 = arguments.remove(0).cast()?;
		Ok(Self::I64(fastrand::i64(min..=max)))
	}
	pub fn function_uuid(arguments: Vec<Self>) -> Result<Self> {
		expect_arguments!(arguments, 0);
		Ok(Self::Str(Uuid::new_v4().to_hyphenated().to_string())) // TODO: Custom type
	}

	pub fn function_pow(mut arguments: Vec<Self>) -> Result<Self> {
		expect_arguments!(arguments, 2);
		arguments.remove(0).pow(arguments.remove(0))
	}

	pub fn function_convert(mut arguments: Vec<Self>) -> Result<Self> {
		optional_expect_arguments!(arguments, 2, 3);
		let datatype: String = arguments.remove(0).convert()?;
		let value = arguments.remove(0);
		let rule = if !arguments.is_empty() {
			arguments.remove(0)
		} else {
			Self::I64(0)
		};
		Ok(match datatype.to_uppercase().as_str() {
			// Unfortunatly we cannot get datatype directly, it needs to be given as string
			"BOOLEAN" => Value::Bool(value.cast_with_rule(rule)?),
			"INTEGER" => Value::I64(value.cast_with_rule(rule)?),
			"FLOAT" => Value::F64(value.cast_with_rule(rule)?),
			"TEXT" => Value::Str(value.cast_with_rule(rule)?),
			"TIMESTAMP" => {
				// Temp, need Value::Timestamp
				let datetime: NaiveDateTime = value.cast_with_rule(rule)?;

				Value::I64(datetime.timestamp())
			}
			_ => return Err(ValueError::UnimplementedConvert.into()),
		})
	}
	pub fn function_try_convert(arguments: Vec<Self>) -> Result<Self> {
		Ok(Value::function_convert(arguments).unwrap_or(Value::Null))
	}
}