use crate::device::device::{Connector, Endpoint, RecordOptions, TranscribeOptions};
use crate::device::shared::{AiOptions, CallControl};
use crate::device::utils::{get_caller_id, get_listen, get_transcribe};
use crate::{format_number, ConnectState, FlowState, NumberFormat, RecordReference};
use cal_jambonz::dial::TranscribeDial;
use cal_jambonz::listen::Listen;
use cal_jambonz::shared::shared::SIPStatus;
use serde::{Deserialize, Serialize};
use std::fmt::{Debug, Formatter};
#[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct Client {
pub username: String,
pub password: String,
#[serde(default = "crate::device::shared::build_client_profile")]
pub profile: ClientProfile,
pub user: Option<RecordReference>,
#[serde(default = "crate::device::shared::build_format")]
pub format: NumberFormat,
#[serde(default = "crate::device::shared::build_present")]
pub present: String,
#[serde(default = "crate::device::shared::build_country_code")]
pub country_code: String,
#[serde(default = "crate::device::shared::build_connect_to")]
pub on_complete: String,
#[serde(default = "crate::device::shared::build_connect_to")]
pub on_busy: String,
#[serde(default = "crate::device::shared::build_connect_to")]
pub on_fail: String,
#[serde(default = "crate::device::shared::build_connect_to")]
pub on_no_answer: String,
#[serde(default = "crate::device::shared::build_ring_time")]
pub ring_time: u8,
#[serde(default = "crate::device::shared::build_call_time")]
pub max_call_time: u16,
#[serde(default)]
pub transcribe_options: TranscribeOptions,
#[serde(default)]
pub record_options: RecordOptions,
#[serde(default)]
pub ai_options: AiOptions,
#[serde(default)]
pub call_control: CallControl,
}
impl Endpoint for Client {
fn get_caller_id(&self, state: &FlowState) -> String {
get_caller_id(&self.format, state)
}
fn get_called_id(&self, state: &FlowState) -> String {
let country_code = state.account.country_code();
let mut called_id = match state.data.get("to") {
Some(dt) => dt.value.clone(),
None => state.initial_request.to.clone(),
};
called_id = format_number(
called_id.as_str(),
state.account.country_code(),
&self.format,
);
match self.profile {
ClientProfile::GenericSoftphone
| ClientProfile::CallablePhone
| ClientProfile::Avaya
| ClientProfile::Generic => called_id,
ClientProfile::GenericE164Plus => {
format_number(called_id.as_str(), country_code, &NumberFormat::E164Plus)
}
ClientProfile::AvayaE164 => {
format_number(called_id.as_str(), country_code, &NumberFormat::E164)
}
}
}
fn get_listen(&self, state: &FlowState) -> Option<Listen> {
get_listen(&self.record_options, self.ai_options.clone(), state)
}
fn get_transcribe(&self, _state: &FlowState) -> Option<TranscribeDial> {
get_transcribe(self.transcribe_options.clone())
}
}
impl Connector for Client {
fn get_connect_to(&mut self, state: &mut FlowState) -> ConnectState {
match &state.get_dial_status() {
Some(status) => match status {
SIPStatus::Ok => ConnectState::complete(self.on_complete.as_str()),
SIPStatus::RequestTerminated => ConnectState::no_answer(self.on_no_answer.as_str()),
SIPStatus::BusyHere | SIPStatus::BusyEverywhere => {
ConnectState::busy(self.on_busy.as_str())
}
_ => ConnectState::fail(self.on_fail.as_str()),
},
None => ConnectState::dialling(),
}
}
}
#[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum ClientProfile {
Generic,
GenericE164Plus,
GenericSoftphone,
CallablePhone,
Avaya,
AvayaE164,
}
impl Debug for Client {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
f.debug_struct("Client")
.field("username", &self.username)
.field("password", &"REDACTED")
.field("profile", &self.profile)
.field("user", &self.user)
.field("format", &self.format)
.field("present", &self.present)
.field("country_code", &self.country_code)
.field("on_complete", &self.on_complete)
.field("on_busy", &self.on_busy)
.field("on_fail", &self.on_fail)
.field("on_no_answer", &self.on_no_answer)
.field("ring_time", &self.ring_time)
.field("max_call_time", &self.max_call_time)
.field("transcribe_options", &self.transcribe_options)
.field("record_options", &self.record_options)
.field("ai_options", &self.ai_options)
.field("call_control", &self.call_control)
.finish()
}
}
impl Debug for ClientProfile {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
ClientProfile::GenericE164Plus => write!(f, "GenericE164Plus"),
ClientProfile::CallablePhone => write!(f, "CallablePhone"),
ClientProfile::Avaya => write!(f, "Avaya"),
ClientProfile::Generic => write!(f, "Generic"),
ClientProfile::GenericSoftphone => write!(f, "GenericSoftphone"),
ClientProfile::AvayaE164 => write!(f, "AvayaE164"),
}
}
}
impl Debug for NumberFormat {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
NumberFormat::National => write!(f, "National"),
NumberFormat::E164Plus => write!(f, "E164+"),
NumberFormat::E164 => write!(f, "E164"),
}
}
}