use crate::{ContactRef, RecordReference};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, VecDeque};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct QueueGroup {
pub name: String,
#[serde(rename = "type")]
#[serde(skip_serializing_if = "Option::is_none")]
pub queue_type: Option<String>,
pub device_id: String,
pub account_id: String,
pub entries: VecDeque<Entry>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Entry {
pub call_sid: String,
pub from: String,
pub priority: i32,
pub timestamp: i64,
#[serde(skip_serializing_if = "Option::is_none")]
pub contact: Option<ContactRef>,
}
impl QueueGroup {
pub fn new(name: String, queue_type: Option<String>, device_id: String, account_id: String) -> Self {
Self {
name,
queue_type,
device_id,
account_id,
entries: VecDeque::new(),
}
}
pub fn get_type(&self) -> String {
self.queue_type.clone().unwrap_or_else(|| "callable-queue".to_string())
}
pub fn add(&mut self, call_sid: String, from: String, priority: i32, contact: Option<ContactRef>) -> Entry {
let entry = Entry {
call_sid: call_sid.clone(),
from,
priority,
timestamp: chrono::Utc::now().timestamp_millis(),
contact,
};
self.entries.push_back(entry.clone());
entry
}
pub fn remove(&mut self, call_sid: &str) {
self.entries.retain(|entry| entry.call_sid != call_sid);
}
pub fn pop(&mut self) -> Option<Entry> {
self.entries.pop_front()
}
pub fn pop_by_priority(&mut self) -> Option<Entry> {
if self.entries.is_empty() {
return None;
}
let min_index = self.entries
.iter()
.enumerate()
.min_by_key(|(_, entry)| entry.get_prioritized_timestamp())
.map(|(index, _)| index)?;
self.entries.remove(min_index)
}
}
impl Entry {
pub fn get_prioritized_timestamp(&self) -> i64 {
self.timestamp * (self.priority as i64) * -1
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct QueueStat {
#[serde(rename = "_id")]
pub id: String,
pub timestamp: DateTime<Utc>,
pub meta: MetaData,
pub entry: Entry,
#[serde(skip_serializing_if = "Option::is_none")]
pub user: Option<RecordReference>,
#[serde(skip_serializing_if = "Option::is_none")]
pub contact: Option<ContactRef>,
pub queue_name: String,
pub queue_time: Option<i64>,
pub queue_count: Option<i64>,
pub status: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<BTreeMap<String, String>>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MetaData {
pub account: RecordReference,
pub device: RecordReference,
}
impl QueueStat {
pub fn new(
id: String,
timestamp: DateTime<Utc>,
meta: MetaData,
entry: Entry,
user: Option<RecordReference>,
contact: Option<ContactRef>,
queue_name: String,
queue_time: Option<i64>,
queue_count: Option<i64>,
status: String,
data: Option<BTreeMap<String, String>>,
) -> Self {
Self {
id,
timestamp,
meta,
entry,
user,
contact,
queue_name,
queue_time,
queue_count,
status,
data,
}
}
}
impl MetaData {
pub fn new(account: RecordReference, device: RecordReference) -> Self {
Self { account, device }
}
}
impl std::fmt::Display for QueueStat {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"QueueStat(id={}, timestamp={}, meta={:?}, entry={:?}, user={:?}, contact={:?}, \
queueName={}, queueTime={:?}, queueCount={:?}, status={}, data={:?})",
self.id,
self.timestamp,
self.meta,
self.entry,
self.user,
self.contact,
self.queue_name,
self.queue_time,
self.queue_count,
self.status,
self.data
)
}
}
impl std::fmt::Display for MetaData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"QueueStat.MetaData(account={:?}, device={:?})",
self.account, self.device
)
}
}