use std::collections::HashMap;
use crate::interface::Installer;
use crate::interface::PostInstall;
use crate::interface::PostUninstall;
use crate::interface::Interface;
use crate::interface::InstallMethod;
use crate::common::get_install_dir;
pub struct InstallerBuilder<'a>
{
name: &'static str,
version: &'static str,
author: &'static str,
install: &'a mut dyn Installer,
user_install: bool,
sys_install: bool,
post_install: Option<&'a mut dyn PostInstall>,
post_uninstall: Option<&'a mut dyn PostUninstall>,
resources: HashMap<&'static str, &'static [u8]>
}
impl <'a> InstallerBuilder<'a>
{
pub fn new(install: &'a mut dyn Installer) -> InstallerBuilder
{
return InstallerBuilder
{
name: "Generic",
version: "1.0",
author: "Unknown",
install: install,
user_install: false,
sys_install: false, post_install: None,
post_uninstall: None,
resources: HashMap::new()
};
}
pub fn set_name(mut self, name: &'static str) -> Self
{
self.name = name;
return self;
}
pub fn set_version(mut self, version: &'static str) -> Self
{
self.version = version;
return self;
}
pub fn set_author(mut self, author: &'static str) -> Self
{
self.author = author;
return self;
}
pub fn add_resource(mut self, path: &'static str, bytes: &'static [u8]) -> Self
{
self.resources.insert(path, bytes);
return self;
}
pub fn add_post_install_step(mut self, obj: &'a mut dyn PostInstall) -> Self
{
self.post_install = Some(obj);
return self;
}
pub fn add_post_uninstall_step(mut self, obj: &'a mut dyn PostUninstall) -> Self
{
self.post_uninstall = Some(obj);
return self;
}
pub fn allow_user_install(mut self) -> Self
{
self.user_install = true;
return self;
}
pub fn allow_system_install(mut self) -> Self
{
self.sys_install = true;
return self;
}
fn run_internal<TInterface: Interface>(&mut self, interface: &mut TInterface) -> Result<(), TInterface::ErrorType>
{
interface.welcome(self.name, self.version, self.author)?;
let mut method = InstallMethod::SystemInstall;
if self.user_install && !self.sys_install
{
method = InstallMethod::UserInstall;
}
else if self.user_install && self.sys_install
{
method = interface.get_install_method()?;
}
let uninstall = interface.should_uninstall()?;
let dir = get_install_dir(&method);
if uninstall
{
interface.run_uninstall(self.install, &dir, method, &self.resources)?;
if let Some(obj) = &mut self.post_uninstall
{
interface.run_post_uninstall(*obj, &dir)?;
}
}
else
{
interface.run_install(self.install, &dir, method, &self.resources)?;
if let Some(obj) = &mut self.post_install
{
interface.run_post_install(*obj, &dir)?;
}
}
return Ok(());
}
pub fn run<TInterface: Interface>(&mut self, interface: &mut TInterface) -> i32
{
match self.run_internal(interface)
{
Ok(()) => interface.finish(),
Err(e) => interface.error(e)
}
}
}