#include "conf-update.h"

char *get_real_filename(const char *update) {
	char *file = (char *)calloc(strlen(update) + 1 - strlen("._cfg????_"), sizeof(char));
	strncpy(file, update, strrchr(update, '/') - update + 1);
	strcat(file, strrchr(update, '/') + strlen("._cfg????_") + 1);
	
	return file;
}

char *get_highest_update(char **index, char *update) {
	// update is just any update of the real file we want to get the highest update for
	char *real_file = get_real_filename(update);
	char *my_real_file;
	char *highest_update = update;
	int i;
	
	for (i=0;!is_last_entry(index[i]);i++) {
		if (is_valid_entry(index[i])) {
			my_real_file = get_real_filename(index[i]);
			if (!strcmp(my_real_file, real_file)) {
				if (strcmp(index[i], highest_update) > 0) {
					highest_update = index[i];
				}
			}
			free(my_real_file);
		}
	}
	
	free(real_file);
	
	return highest_update;
}

bool is_last_entry(const char *entry) {
	if (entry == LAST_ENTRY) {
		return TRUE;
	} else {
		return FALSE;
	}
}

bool is_valid_entry(const char *entry) {
	if (entry == LAST_ENTRY || entry == SKIP_ENTRY) {
		return FALSE;
	} else {
		return TRUE;
	}
}

void merge(char *update, char **index) {
	char *real_file = get_real_filename(update);
	char *my_real_file;
	int i;
	
	exit_error(!rename(update, real_file), update);
	
	for (i=0;!is_last_entry(index[i]);i++) {
		if (is_valid_entry(index[i])) {
			my_real_file = get_real_filename(index[i]);
			if (!strcmp(my_real_file, real_file)) {
				if (strcmp(update, index[i])) {
					exit_error(!unlink(index[i]), index[i]);
				}
				free(index[i]);
				index[i] = SKIP_ENTRY;
			}
			free(my_real_file);
		}
	}
	
	free(real_file);
}

int show_diff(char *update) {
	extern struct configuration config;
	char *realfile = get_real_filename(update);
	char *esc_realfile = g_shell_quote(realfile);
	char *esc_update = g_shell_quote(update);
	char *cmd = (char *)calloc(strlen(config.diff_tool) + strlen(" % % | ") + strlen(esc_update) + strlen(esc_realfile) + strlen(config.pager) + 1, sizeof(char));
	int ret;

	strcpy(cmd, config.diff_tool);
	strcat(cmd, " ");
	strcat(cmd, esc_realfile);
	strcat(cmd, " ");
	strcat(cmd, esc_update);
	if (strcmp(config.pager, "")) {
		strcat(cmd, " | ");
		strcat(cmd, config.pager);
	}
	ret = system(cmd);
	free(realfile);
	g_free(esc_realfile);
	g_free(esc_update);
	free(cmd);
	return ret;
}

int edit_update(char *update) {
	extern struct configuration config;
	char *esc_update = g_shell_quote(update);
	char *cmd = calloc(strlen(config.edit_tool) + strlen("  ") + strlen(esc_update), sizeof(char));
	int ret;
	
	strcpy(cmd, config.edit_tool);
	strcat(cmd, " ");
	strcat(cmd, esc_update);
	
	ret = system(cmd);
	g_free(esc_update);
	free(cmd);
	return ret;
}

char **merge_interactively(char *update, char **index) {
	// customized versions are ._cfg????- with a minus instead of a underscore
	// that way get_real_filename() works without modification
	extern struct configuration config;
	char *realfile = get_real_filename(update);
	char *esc_realfile = g_shell_quote(realfile);
	char *esc_update = g_shell_quote(update);
	char *cmd = calloc(strlen("clear ; ") + strlen(config.merge_tool) + 2 * strlen(esc_update) + strlen(esc_realfile) + strlen(" % % %"), sizeof(char));
	char *merged, *esc_merged;
	char **new_index = index;
	int retval, ct;
	
	// interactively merge an interactively merged file? naah.
	if (*(strstr(update, "._cfg") + strlen("._cfg????")) == '_') {
		merged = strdup(update);
		*(strstr(merged, "._cfg") + strlen("._cfg????")) = '-';
		esc_merged = g_shell_quote(merged);
		strcpy(cmd, "clear ; ");
		strcat(cmd, config.merge_tool);
		strcat(cmd, " ");
		strcat(cmd, esc_merged);
		strcat(cmd, " ");
		strcat(cmd, esc_realfile);
		strcat(cmd, " ");
		strcat(cmd, esc_update);
		retval = WEXITSTATUS(system(cmd));

		if (retval == 0 || retval == 1) {
			for (ct=0;!is_last_entry(index[ct]);ct++) {}
			new_index = realloc(index, (ct + 2) * sizeof(char *));
			new_index[ct] = strdup(merged);
			new_index[ct+1] = LAST_ENTRY;
		} else {
			// user aborted or error
			unlink(merged);
		}
		free(merged);
		g_free(esc_merged);
	}
	free(cmd);
	free(realfile);
	g_free(esc_realfile);
	g_free(esc_update);
	
	return new_index;
}
void display_help() {
	char *str = \
	"Usage: " PROG_NAME " [options] [location1] [locationN] ...\n\n"
	
	"Options:\n"
		"\t--help (-h)  Show this message\n"
	"\n"
	"Locations: absolute path to a directory to search through\n"
	"           instead of CONFIG_PROTECT\n"
	"\n"
	"Shortcuts: \n"
		"\tSelecting a directory will select all its updates\n";
	
	
	fprintf(stderr, "%s", str);
	exit(EXIT_SUCCESS);
}
