bleur 0.0.2

That buddy that will get everything ready for you
Documentation
use crate::{
    method::{Fetchable, Method, Methodical},
    schemes::Configuration,
    Error, Result,
};
use std::path::Path;
use tempfile::{tempdir, TempDir};
use url::Url;

#[derive(Debug)]
pub struct Manager {
    remote: Url,
    temporary: TempDir,
    method: Method,
    template: Configuration,
}

impl Manager {
    pub fn new(remote: Url, temporary: TempDir, method: Method) -> Self {
        Self {
            remote,
            temporary,
            method,
            template: Default::default(),
        }
    }

    pub async fn instantiate(self) -> Result<Self> {
        self.method.fetch().await?;

        Ok(Self {
            remote: self.remote,
            temporary: self.temporary,
            method: self.method,
            template: self.template,
        })
    }

    pub fn parse(self) -> Result<Self> {
        let templates = Configuration::parse(self.temporary.path().to_path_buf());

        if let Configuration::Empty = templates {
            return Err(Error::NoTemplateConfiguration);
        }

        Ok(Self {
            remote: self.remote,
            temporary: self.temporary,
            method: self.method,
            template: templates,
        })
    }

    pub fn path(&self) -> &Path {
        self.temporary.path()
    }
}

#[derive(Default, Debug)]
pub struct ManageBuilder {
    remote: Option<Url>,
    temporary: Option<TempDir>,
    method: Option<Method>,
}

impl ManageBuilder {
    pub fn new() -> Self {
        Self {
            remote: None,
            temporary: None,
            method: None,
        }
    }

    pub fn tempdir(self) -> Result<Self> {
        Ok(Self {
            remote: self.remote,
            temporary: Some(tempdir().map_err(Error::TemporaryCantCreate)?),
            method: self.method,
        })
    }

    pub fn source<T>(self, url: T) -> Result<Self>
    where
        T: AsRef<str>,
    {
        Ok(Self {
            temporary: self.temporary,
            method: self.method,
            remote: match Url::parse(url.as_ref()) {
                Ok(l) => Some(l),
                Err(e) => return Err(Error::CantParseUrl(e)),
            },
        })
    }

    pub fn fetch_method<T>(self, method: T) -> Result<Self>
    where
        T: Methodical,
    {
        if self.temporary.is_none() || self.remote.is_none() {
            return Err(Error::InsufficientArgumentsToDecide);
        }

        let destination = self.temporary.unwrap();

        let method = method.to_method(
            self.remote.clone().unwrap(),
            destination.path().to_path_buf(),
        );

        Ok(Self {
            method: Some(method),
            remote: self.remote,
            temporary: Some(destination),
        })
    }

    pub fn build(self) -> Result<Manager> {
        Ok(Manager::new(
            self.remote.unwrap(),
            self.temporary.unwrap(),
            self.method.unwrap(),
        ))
    }
}