
use tera::{Tera,Context};
use tokio::sync::RwLock;

#[cfg(feature = "casbin")]
use casbin::{CoreApi,Enforcer};
#[cfg(feature = "casbin")]
use std::{
    path::Path,
    sync::Arc,
};

use crate::defs::{
    Config,
    SessionStoreDB,
};

#[cfg(feature = "authstore")]
use crate::defs::AuthStore;

use crate::users::UserStore;

#[cfg(feature = "authstore")]
#[derive(Clone)]
pub struct AppDBs {
    pub config: Config,
    pub auth_store: AuthStore,
    pub sessions_store_db: SessionStoreDB,
    pub user_store: UserStore,
    pub tera: Tera,
    pub context: Context,
}
#[cfg(feature = "authstore")]
impl AppDBs {
    pub fn new(config: &Config, store: SessionStoreDB, user_store: UserStore, tera: Tera, context: Context) -> Self {
        Self {
            config: config.to_owned(),
            auth_store: AuthStore::new(&config.authz_store_uri),
            sessions_store_db: store,
            user_store,
            tera,
            context,
        }
    } 
}
#[cfg(feature = "casbin")]
#[derive(Clone)]
pub struct AppDBs {
    pub config: Config,
    pub enforcer: Arc<RwLock<Enforcer>>,
    pub sessions_store_db: SessionStoreDB,
    pub user_store: UserStore,
    pub tera: Tera,
    pub context: Context,
}
#[cfg(feature = "casbin")]
impl AppDBs {
    pub fn new(config: &Config, store: SessionStoreDB, user_store: UserStore, enforcer: Arc<RwLock<Enforcer>>, tera: Tera, context: Context) -> Self {
        Self {
            config: config.to_owned(),
            enforcer,
            sessions_store_db: store,
            user_store,
            tera,
            context,
        }
    } 
    pub async fn create_enforcer(model_path: &'static str, policy_path: &'static str) -> Arc<RwLock<Enforcer>> {
        if ! Path::new(&model_path).exists() {
            panic!("model path: {} not exists",&model_path);
        }
        if ! Path::new(&policy_path).exists() {
            panic!("policy path: {} not exists",&policy_path);
        }
        let e = Enforcer::new(model_path, policy_path)
            .await
            .expect("can read casbin model and policy files");
        Arc::new(RwLock::new(e))
    }
}


