use crate::data::Data;
use crate::shell::is_privileged;
use colored::*;
use pay_respects_utils::evals::split_command;

// to_string() is necessary here, otherwise there won't be color in the output
#[warn(clippy::unnecessary_to_owned)]
pub fn highlight_difference(data: &Data, suggested_command: &str, active: bool) -> Option<String> {
	// let replaced_newline = suggested_command.replace('\n', r" {{newline}} ");
	let shell = &data.shell;
	let last_command = &data.command;
	let mut split_suggested_command = split_command(suggested_command);
	let split_last_command = split_command(last_command);

	if split_suggested_command == split_last_command {
		return None;
	}
	if split_suggested_command.is_empty() {
		return None;
	}

	let privileged = is_privileged(data, &split_suggested_command[0]);

	let mut old_entries = Vec::new();
	for command in &split_suggested_command {
		if command.is_empty() {
			continue;
		}
		for old in split_last_command.clone() {
			if command == &old {
				old_entries.push(command.clone());
				break;
			}
		}
	}

	let mut skip = false;

	'next: for entry in split_suggested_command.iter_mut() {
		if entry == "#" {
			skip = true;
			continue;
		}
		if entry == "\n" {
			skip = false;
			continue;
		}
		if skip {
			*entry = entry.normal().to_string();
			continue;
		}
		for old in &old_entries {
			if old == entry {
				*entry = color_same(entry, active).to_string();
				continue 'next;
			}
		}
		*entry = color_diff(entry, active);
	}

	if privileged
		&& (suggested_command.contains("&&")
			|| suggested_command.contains("||")
			|| suggested_command.contains('>'))
	{
		split_suggested_command[1] =
			color_diff(&format!("{} -c \"\n", shell), active) + &split_suggested_command[1];
		let len = split_suggested_command.len() - 1;
		split_suggested_command[len] =
			split_suggested_command[len].clone() + color_diff("\n\"", active).as_str();
	}

	if let Some(sudo) = data.privilege.clone() {
		if suggested_command.contains("&&")
			|| suggested_command.contains("||")
			|| suggested_command.contains('>')
		{
			split_suggested_command[0] =
				color_same(&format!("{} -c \"\n", shell), active) + &split_suggested_command[0];
			let len = split_suggested_command.len() - 1;
			split_suggested_command[len] =
				split_suggested_command[len].clone() + color_same("\n\"", active).as_str();
		}
		split_suggested_command.insert(0, color_same(&sudo, active));
	}

	let highlighted = split_suggested_command.join(" ").replace(" \n ", "\n");

	Some(highlighted)
}

fn color_same(str: &str, active: bool) -> String {
	if active {
		str.blue().to_string()
	} else {
		str.normal().to_string()
	}
}

fn color_diff(str: &str, active: bool) -> String {
	if active {
		str.red().bold().to_string()
	} else {
		str.normal().bold().to_string()
	}
}
