use std::collections::HashSet;
use anyhow::{bail, Context, Result};
use log::info;
use molar::prelude::*;
pub(super) fn command_rearrange(
infile: &str,
outfile: &str,
begin: &Vec<String>,
end: &Vec<String>,
) -> Result<()> {
if begin.is_empty() && end.is_empty() {
bail!("Provide at least one selection for rearranging!");
}
if !begin.is_empty() {
info!("Selections to put in the beginning:");
for s in begin.iter() {
info!("\t{s}");
}
}
if !end.is_empty() {
info!("Selections to put at the end:");
for s in end.iter() {
info!("\t{s}");
}
}
info!("Rearranging file '{infile}'...");
let in_sys = System::from_file(infile)?;
let begin_sels = begin
.iter()
.map(|s| in_sys.select_bound(s))
.collect::<Result<Vec<_>,_>>()
.with_context(|| "can't create begin selections for rearranging")?;
let end_sels = end
.iter()
.map(|s| in_sys.select_bound(s))
.collect::<Result<Vec<_>,_>>()
.with_context(|| "can't create end selections for rearranging")?;
let mut used = HashSet::<usize>::default();
for sel in begin_sels.iter().chain(end_sels.iter()) {
for i in sel.iter_index() {
if !used.insert(i) {
bail!("selections for rearrangement overlap at atom {i}");
}
}
}
let all_ind = (0..in_sys.len()).collect::<HashSet<usize>>();
let rest_sel = in_sys
.select_bound(all_ind.difference(&used).cloned().collect::<Vec<_>>())
.ok();
let mut out = System::default();
for sel in begin_sels {
out.append(&sel)?;
}
if let Some(rest) = rest_sel {
info!("There are {} untouched atoms", rest.len());
out.append(&rest)?;
}
for sel in end_sels {
out.append(&sel)?;
}
info!("Writing rearranged to '{outfile}'...");
out.save(outfile)?;
Ok(())
}