use std::ops::Deref;
use crate::{
MaaResult,
common::{MaaId, MaaStatus},
sys,
};
pub type StatusFn<'a> = Box<dyn Fn(MaaId) -> MaaStatus + Send + Sync + 'a>;
pub type WaitFn<'a> = Box<dyn Fn(MaaId) -> MaaStatus + Send + Sync + 'a>;
pub struct Job<'a> {
pub id: MaaId,
status_fn: StatusFn<'a>,
wait_fn: WaitFn<'a>,
}
impl<'a> Job<'a> {
pub fn new(id: MaaId, status_fn: StatusFn<'a>, wait_fn: WaitFn<'a>) -> Self {
Self {
id,
status_fn,
wait_fn,
}
}
pub fn for_tasker(tasker: &crate::tasker::Tasker, id: MaaId) -> Job<'static> {
let tasker1 = tasker.clone();
let tasker2 = tasker.clone();
Job {
id,
status_fn: Box::new(move |job_id| {
MaaStatus(unsafe { sys::MaaTaskerStatus(tasker1.raw(), job_id) })
}),
wait_fn: Box::new(move |job_id| {
MaaStatus(unsafe { sys::MaaTaskerWait(tasker2.raw(), job_id) })
}),
}
}
pub fn for_controller(controller: &crate::controller::Controller, id: MaaId) -> Job<'static> {
let controller1 = controller.clone();
let controller2 = controller.clone();
Job {
id,
status_fn: Box::new(move |job_id| {
MaaStatus(unsafe { sys::MaaControllerStatus(controller1.raw(), job_id) })
}),
wait_fn: Box::new(move |job_id| {
MaaStatus(unsafe { sys::MaaControllerWait(controller2.raw(), job_id) })
}),
}
}
pub fn for_resource(resource: &crate::resource::Resource, id: MaaId) -> Job<'static> {
let resource1 = resource.clone();
let resource2 = resource.clone();
Job {
id,
status_fn: Box::new(move |job_id| {
MaaStatus(unsafe { sys::MaaResourceStatus(resource1.raw(), job_id) })
}),
wait_fn: Box::new(move |job_id| {
MaaStatus(unsafe { sys::MaaResourceWait(resource2.raw(), job_id) })
}),
}
}
pub fn wait(&self) -> MaaStatus {
(self.wait_fn)(self.id)
}
pub fn status(&self) -> MaaStatus {
(self.status_fn)(self.id)
}
pub fn succeeded(&self) -> bool {
self.status() == MaaStatus::SUCCEEDED
}
pub fn failed(&self) -> bool {
self.status() == MaaStatus::FAILED
}
pub fn running(&self) -> bool {
self.status() == MaaStatus::RUNNING
}
pub fn pending(&self) -> bool {
self.status() == MaaStatus::PENDING
}
pub fn done(&self) -> bool {
let s = self.status();
s == MaaStatus::SUCCEEDED || s == MaaStatus::FAILED
}
}
pub struct JobWithResult<'a, T> {
job: Job<'a>,
get_fn: Box<dyn Fn(MaaId) -> MaaResult<Option<T>> + Send + Sync + 'a>,
}
impl<'a, T> Deref for JobWithResult<'a, T> {
type Target = Job<'a>;
fn deref(&self) -> &Self::Target {
&self.job
}
}
impl<'a, T> JobWithResult<'a, T> {
pub fn new(
id: MaaId,
status_fn: StatusFn<'a>,
wait_fn: WaitFn<'a>,
get_fn: impl Fn(MaaId) -> MaaResult<Option<T>> + Send + Sync + 'a,
) -> Self {
Self {
job: Job::new(id, status_fn, wait_fn),
get_fn: Box::new(get_fn),
}
}
pub fn get(&self, wait: bool) -> MaaResult<Option<T>> {
if wait {
self.wait();
}
(self.get_fn)(self.job.id)
}
}
pub type OverridePipelineFn<'a> = Box<dyn Fn(MaaId, &str) -> MaaResult<bool> + Send + Sync + 'a>;
pub struct TaskJob<'a, T> {
job: JobWithResult<'a, T>,
override_fn: OverridePipelineFn<'a>,
}
impl<'a, T> Deref for TaskJob<'a, T> {
type Target = JobWithResult<'a, T>;
fn deref(&self) -> &Self::Target {
&self.job
}
}
impl<'a, T> TaskJob<'a, T> {
pub fn new(job: JobWithResult<'a, T>, override_fn: OverridePipelineFn<'a>) -> Self {
Self { job, override_fn }
}
pub fn override_pipeline(&self, pipeline_override: &str) -> MaaResult<bool> {
(self.override_fn)(self.job.id, pipeline_override)
}
}
pub type CtrlJob = Job<'static>;
pub type ResJob = Job<'static>;
pub type TaskJobWithResult = TaskJob<'static, crate::common::TaskDetail>;
pub type RecoJobWithResult = TaskJob<'static, crate::common::RecognitionDetail>;
pub type ActionJobWithResult = TaskJob<'static, crate::common::ActionDetail>;