#[cfg(feature = "rt")]
mod gate {
  use std::{sync::mpsc, time::Duration};

  #[derive(Debug)]
  enum MyError {}

  use qsu::{
    rt::{
      Demise, InitCtx, RunCtx, RunEnv, ServiceHandler, SrvAppRt, SvcEvt,
      TermCtx, UserSig
    },
    tracing
  };

  struct MyService {
    rx_term: mpsc::Receiver<()>
  }

  impl ServiceHandler for MyService {
    type AppErr = MyError;

    fn init(&mut self, _ictx: &mut InitCtx) -> Result<(), Self::AppErr> {
      tracing::info!("Running ServiceHandler::init()");
      Ok(())
    }

    fn run(&mut self, _re: &RunEnv) -> Result<(), Self::AppErr> {
      tracing::info!("Running ServiceHandler::run()");

      tracing::info!("Wait for termination event for up to 4 seconds ..");
      let _ = self.rx_term.recv_timeout(Duration::from_secs(4));

      Ok(())
    }

    fn shutdown(&mut self, _tctx: &mut TermCtx) -> Result<(), Self::AppErr> {
      tracing::info!("Running ServiceHandler::shutdown()");
      Ok(())
    }
  }


  pub fn main() {
    let svcname = qsu::default_service_name().unwrap();

    // Channel used to signal termination from service event handler to main
    // application
    let (tx, rx) = mpsc::channel::<()>();

    // Service event handler
    let svcevt_handler = move |msg| match msg {
      SvcEvt::Shutdown(demise) => {
        tracing::debug!("Shutdown event received");
        match demise {
          Demise::Interrupted => {
            tracing::info!("Service application was interrupted");
          }
          Demise::Terminated => {
            tracing::info!("Service application was terminated");
          }
          Demise::ReachedEnd => {
            tracing::info!("Service application reached its end");
          }
        }

        // Once a Shutdown event has been received, signal to the main service
        // callback to terminate.
        tx.send(()).unwrap();
      }
      SvcEvt::User(us) => match us {
        UserSig::Sig1 => {
          log::info!("User signal 1");
        }
        UserSig::Sig2 => {
          log::info!("User signal 2");
        }
      },
      _ => {}
    };

    // Set up main service runtime handler
    let svcrt = MyService { rx_term: rx };

    // Define service application runtime components
    let apprt = SrvAppRt::Sync {
      svcevt_handler: Box::new(svcevt_handler),
      rt_handler: Box::new(svcrt)
    };

    // Launch service
    let rctx = RunCtx::new(&svcname);
    rctx.run(apprt).unwrap();
  }
}


fn main() {
  #[cfg(feature = "rt")]
  gate::main();

  #[cfg(not(feature = "rt"))]
  println!("simplesync example requires the rt feature");
}

// vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :
