use crate::domain;
use json::JsonRepository;
use std::string::String;
pub mod json;
mod test;

pub trait Repository {
    fn save(&mut self, user: &domain::User) -> Result<(), Error>;
    fn load(&self, user: &String) -> Result<domain::User, Error>;
    fn update(&mut self, original_user: &String, user: &domain::User) -> Result<(), Error>;
    fn delete(&mut self, user: &String) -> Result<(), Error>;
    fn clear(&mut self) -> Result<(), Error>;
    fn size(&self) -> Result<usize, Error>;
}
#[derive(Debug)]
pub enum Error {
    NotAbleToLoadData(String),
    UserDontExist,
    NotAbleToSave(String),
    NotAbleToAccesRepository(String),
    NotAbleToInstantiateRepository(String),
    UserAlreadyExist,
}

#[derive(Debug)]
pub enum Type {
    Json,
}

pub enum Implementation {
    Json(json::JsonRepository),
}

pub fn provide_repository(
    implementation: Type,
    directory: &String,
) -> Result<Implementation, Error> {
    match implementation {
        Type::Json => match JsonRepository::new(directory) {
            Err(e) => Err(e),
            Ok(r) => Ok(Implementation::Json(r)),
        },
    }
}

impl std::ops::Deref for Implementation {
    type Target = dyn Repository;

    fn deref(&self) -> &Self::Target {
        match self {
            Implementation::Json(x) => x,
        }
    }
}
