use crate::event;
use crate::var;
use log::*;
use spin::Once;
use unmp::id::*;
use unmp::link::{ErrorKind, Link};
use unmp::net;
use unmp::Connection;
use unmp_center_core::{Cmd, Data};
use unmp_protocol_etp::Addr;
const ETP_PORT: u8 = 0x64;
static SEND: Once<SendFun> = Once::new();
static PROTOCOL: Once<Protocol> = Once::new();
static LINK: Once<Link> = Once::new();
static CENTER_ID: Id = UniqueId::new(0, 1).id();
static CENTER_ETP: Addr = Addr::new(UniqueId::new(0, 1).id(), ETP_PORT);
type SendFun = fn(buf: &[u8]);
#[derive(Clone)]
pub enum Protocol {
Raw,
Etp(u8),
}
fn solve(data: &Data) {
match data.cmd() {
Cmd::GetIdRes {
device_id,
private_key,
public_key,
} => {
event::emit_getid(device_id, private_key, public_key);
}
Cmd::LoginRes {} => {
event::emit_login();
}
Cmd::HeartRes {} => {}
Cmd::GetTimestampRes { timestamp } => {
event::emit_get_timestamp(*timestamp);
}
Cmd::SetActualRes { id, k, v } => {
var::set_actual(id, *k, v);
}
Cmd::GetActualRes { id, k, v } => {
var::set_actual(id, *k, v);
}
Cmd::NoticeActual { id, k, v } => {
var::set_actual(id, *k, v);
}
Cmd::SetTargetRes { id, k, v } => {
var::set_target(id, *k, v);
}
Cmd::GetTargetRes { id, k, v } => {
var::set_target(id, *k, v);
}
Cmd::NoticeTarget { id, k, v } => {
var::set_target(id, *k, v);
}
Cmd::EnterBindRes { code } => {
event::emit_enter_bind(code);
}
Cmd::BindRes { id, public_key } => {
event::emit_bind(id, public_key);
}
Cmd::UnbindRes { id } => {
event::emit_unbind(id);
}
Cmd::NoticeBind { id, public_key } => {
event::emit_bind(id, public_key);
}
Cmd::NoticeUnbind { id } => {
event::emit_unbind(id);
}
_ => {
event::emit_error(data.kind(), data.status());
info!("{:?}", data);
}
}
}
fn etp_listener(_remote: Addr, buf: &[u8]) {
let data = Data::parse(buf);
solve(&data);
}
fn raw_listener(_remote: Connection, buf: &[u8]) {
let data = Data::parse(buf);
solve(&data);
}
fn sendto(_link: Link, buf: &[u8]) -> Result<(), ErrorKind> {
if let Some(fun) = SEND.get() {
fun(buf);
}
return Ok(());
}
pub fn set_protocol(protocol: Protocol) {
match protocol {
Protocol::Raw => {
unmp_protocol_raw::init();
unmp_protocol_raw::set_recv_cb(raw_listener);
}
Protocol::Etp(_) => {
unmp_protocol_etp::init();
unmp_protocol_etp::listen(ETP_PORT, etp_listener);
}
}
PROTOCOL.call_once(|| protocol);
}
pub fn set_send(fun: SendFun) {
SEND.call_once(|| fun);
let link = Link::new(sendto);
LINK.call_once(|| link);
net::connect(&ID_PARENT, link);
}
pub(crate) fn send(buf: &[u8]) {
match PROTOCOL.get().unwrap() {
Protocol::Raw => {
unmp_protocol_raw::send(&CENTER_ID, buf);
}
Protocol::Etp(retry) => {
unmp_protocol_etp::send(ETP_PORT, &CENTER_ETP, buf, *retry);
}
}
}
pub fn recv(buf: &[u8]) {
let link = LINK.get().unwrap();
net::when_recv(*link, buf);
}