// SPDX-FileCopyrightText: 2023 Gleb Smirnov <glebsmirnov0708@gmail.com>
//
// SPDX-License-Identifier: MIT

//! This module contains high-level API for
//! working with actions.
//!
//! You should always use [`Actions`] instead of
//! using [`ActionProvider`] directly.

pub mod modify;
pub mod perform;
pub mod stop;

use std::{collections::HashMap, rc::Rc};

use crate::{Action, ActionProvider, ActionProviderStop};

use self::stop::StopHandle;

/// Actions from some provider.
///
/// This is a high-level and asynchronous wrapper
/// around [`ActionProvider`].
#[derive(Debug)]
pub struct Actions<P: ActionProvider> {
    /// Action provider that the storage wraps.
    ///
    /// Wrapped in [`Rc`] because you might
    /// want to copy it outside the actions.
    provider: Rc<P>,

    /// Metadata of the actions.
    ///
    /// It's a private field since modifying
    /// it directly will break things.
    actions: HashMap<String, Action>,
}

impl<P: ActionProvider> Actions<P> {
    /// Creates a storage from an action provider.
    pub async fn new(provider: P) -> Result<Self, P::LoadActionsError> {
        let provider = Rc::new(provider);

        let actions = provider.load_actions().await?;

        Ok(Self { actions, provider })
    }

    /// Returns actions' metadata.
    pub fn actions(&self) -> &HashMap<String, Action> {
        &self.actions
    }

    /// Returns reference to inner action provider.
    ///
    /// Use it with caution since you it's possible to break
    /// some [`ActionProvider`] API guarantees using raw provider.
    pub fn provider(&self) -> Rc<P> {
        self.provider.clone()
    }
}

impl<P: ActionProviderStop> Actions<P> {
    /// Creates a stop handle.
    ///
    /// Stop hadle allows to stop all running actions
    /// without dropping all running action futures
    /// and even without [`Actions`] reference.
    pub fn stop_handle(&self) -> StopHandle<P> {
        StopHandle {
            provider: self.provider.clone(),
            stop_on_drop: false,
        }
    }
}
