#!/usr/bin/env rust-script
//! ```cargo
//! [dependencies]
//! anyhow = "1.0.69"
//! dirs = "4.0.0"
//! ```

use anyhow::{anyhow, bail, Context};

use std::{
	fs::{self, File},
	io::{BufRead, BufReader, ErrorKind},
};

const ENV: &str = r#". "$HOME/.cargo/env""#;

fn main() -> anyhow::Result<()> {
	let home = dirs::home_dir().context("can't find home directory")?;
	let mut login_path = home.clone();
	login_path.push(".bash_login");
	let login = match File::open(&login_path) {
		Ok(file) => {
			let login = BufReader::new(file);
			let mut skip = false;
			let mut new_login = String::new();
			let mut removed = false;
			let mut added = false;
			for line in login.lines() {
				let line = line.context("failed to read line in ~/.bash_login")?;
				if line.is_empty() && skip {
					continue;
				}
				skip = line.is_empty();
				if line == ENV {
					removed = true;
				} else {
					new_login.push_str(&line);
					new_login.push('\n');
				}
				if line == "# custom" && !added {
					added = true;
					new_login.push('\n');
					new_login.push_str(ENV);
					new_login.push_str("\n\n");
					skip = true;
				}
			}
			if removed && !added {
				bail!("would remove \"{ENV}\" and not add it back");
			}
			new_login.trim().to_owned() + "\n"
		}
		Err(e) if e.kind() == ErrorKind::NotFound => format!("# custom\n\n{ENV}\n"),
		Err(e) => bail!(anyhow!(e).context("failed to read ~/.bash_login")),
	};
	fs::write(login_path, &login).context("failed to write new ~/.bash_login")?;

	let mut bashrc_path = home.clone();
	bashrc_path.push(".bashrc");
	let bashrc = match File::open(&bashrc_path) {
		Ok(file) => {
			let bashrc = BufReader::new(file);
			let mut skip = false;
			let mut new_bashrc = String::new();
			for line in bashrc.lines() {
				let line = line.context("failed to read line in ~/.bashrc")?;
				if line.is_empty() && skip {
					continue;
				}
				skip = line.is_empty();
				if line != ENV {
					new_bashrc.push_str(&line);
					new_bashrc.push('\n');
				}
			}
			new_bashrc.trim().to_owned() + "\n"
		}
		Err(e) if e.kind() == ErrorKind::NotFound => "# custom\n".to_owned(),
		Err(e) => bail!(anyhow!(e).context("failed to read ~/.bashrc")),
	};
	fs::write(bashrc_path, &bashrc).context("failed to write new ~/.bashrc")?;

	Ok(())
}
