datam 0.2.0

A terminal tool to manager your files.
use sha2::{Digest, Sha256};

use crate::handler::{Context, Handler};
use crate::handler_ipfs::IpfsHandler;
use crate::handler_local::LocalHandler;

pub struct ComposedHandler {
    local: LocalHandler,
    remote: Vec<Box<dyn Handler>>,
}

impl ComposedHandler {
    pub fn new() -> Self {
        Self {
            local: LocalHandler::new(),
            remote: vec![Box::new(IpfsHandler::new())],
        }
    }
}

impl ComposedHandler {
    pub async fn add(&mut self, ctx: Context) -> Context {
        let mut ctx = ctx;
        for handler in self.remote.iter_mut() {
            ctx = handler.add(ctx).await;
        }
        self.local.add(ctx).await
    }

    pub async fn get(&self, ctx: Context) -> Option<Context> {
        let ctx = self.local.get(ctx).await;
        if let Some(mut ctx) = ctx {
            for handler in self.remote.iter() {
                ctx = handler.get(ctx.clone()).await.unwrap_or(ctx);
                if !ctx.get_content().is_empty() {
                    let mut hasher = Sha256::new();
                    hasher.update(ctx.get_content());
                    let sha256 = hasher.finalize().to_vec();
                    if sha256 == *ctx.get_sha256() {
                        return Some(ctx);
                    } else {
                        log::warn!(
                            "Unexpected sha256 with `{}` in remote `{}`",
                            ctx.get_id(),
                            handler.name()
                        );
                    }
                }
            }
            Some(ctx)
        } else {
            None
        }
    }

    pub async fn remove(&mut self, ctx: Context) -> Option<Context> {
        let ctx = self.local.remove(ctx).await;
        if let Some(mut ctx) = ctx {
            for handler in self.remote.iter_mut() {
                ctx = handler.remove(ctx.clone()).await.unwrap_or(ctx);
            }
            Some(ctx)
        } else {
            None
        }
    }

    pub async fn list(&self) -> String {
        self.local.list().await
    }
}