From 6c7290883f5bb09b6b2a98a6d9f8cc397ac42e1a Mon Sep 17 00:00:00 2001
From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com>
Date: Tue, 26 Mar 2024 11:29:47 -0400
Subject: [PATCH] (init) routine methods

---
 src/core/botmodules.rs | 126 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 124 insertions(+), 2 deletions(-)

diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs
index c104fdd..5b725b8 100644
--- a/src/core/botmodules.rs
+++ b/src/core/botmodules.rs
@@ -30,9 +30,13 @@ use std::sync::Arc;
 
 use casual_logger::Log;
 
+use chrono::DateTime;
+use chrono::Duration;
+use chrono::Local;
 use tokio::sync::RwLock;
 
 use async_trait::async_trait;
+use tokio::task::JoinHandle;
 
 use crate::core::bot_actions::actions_util;
 use crate::core::bot_actions::ExecBodyParams;
@@ -568,8 +572,126 @@ impl BotActionTrait for Listener {
     }
 }
 
-#[derive(Debug)]
-pub struct Routine {}
+
+enum RoutineAttr {
+    DelayedStart,
+    ScheduledStart(DateTime<Local>), // Scheduled Date (if any) after which, if not started, may trigger
+    LoopDuration(Duration), // How long to wait between iterations
+    LoopInfinitely,
+    RunOnce,
+    MaxTimeThreshold(DateTime<Local>), // DateTime after which, it will abort/cancel or stop
+    MaxIterations(i64),
+}
+/*
+    a Routine can be given different combinations of the above, but business logic may validate 
+    these at Routine construction
+
+    For example, a Routine could have the following characteristics
+    - DelayedStart (so it skips the first iteration)
+    - ScheduledStart(DateTime<Local>) - With a Start Date-Time for the first iteration to trigger
+    - LoopDuration(Duration) - How long to wait between iterations
+
+    The above without any other thresholds would loop infinitely with the above characteristics 
+
+    Another example,
+    - LoopDuration(Duration) - How long to wait between iterations
+    - MaxTimeThreshold(DateTime<Local>)
+    - MaxIterations(i64) 
+
+    The above has thresholds , so if either are reached, it would abort/cancel or stop . Since there is no 
+    ScheduledStart, the routine would have to be started manually elsewhere
+
+    Another example , 
+    - (no RoutineAttr)
+
+    The above would only run once, and only when the Start() is called
+
+*/
+
+// #[derive(Debug)]
+pub struct Routine {
+    // pub name : String ,
+    module : BotModule , // from() can determine this if passed parents_params
+    // pub channel : Option<Channel> , // Routines generally run by Channel ; but can be left None
+    channel : Channel , // Requiring some channel context 
+    exec_body: bot_actions::actions_util::ExecBody,
+    parent_params : Option<ExecBodyParams> ,
+    join_handle : Option<JoinHandle<()>> , 
+    complete_iterations : i64 , 
+    remaining_iterations : i64 ,
+    start_time : Option<DateTime<Local>> ,
+    routine_attr : Vec<RoutineAttr> ,
+}
+
+
+impl Routine {
+
+    // Constructor
+    pub fn from(
+        _module : BotModule ,
+        _channel : Channel,
+        _exec_body : bot_actions::actions_util::ExecBody ,
+        _parent_params : Option<ExecBodyParams>
+    ) -> Result<String,String> {
+
+        // [ ] Validation is made against parent_params
+        //   to ensure those params don't conflict
+        //   conlicts would throw an error
+
+        Err("NOT IMPLEMENTED".to_string())
+    }
+
+    pub fn change_channel(
+        &self,
+        _channel : Channel
+    ) -> Result<String,String> {
+        // [ ] Think Ideally it should try to 
+        //  change the target channel of the
+        //  internal process too if possible?
+
+        Err("NOT IMPLEMENTED".to_string())
+    }
+
+
+    pub fn start(&self) -> Result<String,String> 
+    {
+
+        // [ ] Asyncio Spawn likely around here 
+        // [ ] & Assigns self.join_handle
+
+        Err("NOT IMPLEMENTED".to_string())
+    }
+
+    pub fn stop(&self) -> Result<String,String> 
+    {
+        Err("NOT IMPLEMENTED".to_string())
+    }
+
+    pub fn restart(
+        &self,
+        _force : bool
+    ) -> Result<String,String> 
+    {
+        // force flag aborts the routine immediately (like cancel())
+        Err("NOT IMPLEMENTED".to_string())
+    }
+
+    pub fn cancel(&self) -> Result<String,String> 
+    {
+
+        // [ ] Likely calls abort()
+        // Related : 
+        // https://docs.rs/tokio/latest/tokio/task/struct.JoinHandle.html#method.abort
+
+        Err("NOT IMPLEMENTED".to_string())
+    }
+
+
+
+}
+
+
+
 
 type StatusdbEntry = (ModGroup, Vec<StatusType>);
 type ModuleActions = Vec<Arc<RwLock<BotAction>>>;