#include "builtins.h"

#include <errno.h>
#include <limits.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "sish.h"

bool
is_builtin(const char* cmd)
{
	return strcmp(cmd, "cd") == 0 || strcmp(cmd, "echo") == 0 ||
	       strcmp(cmd, "exit") == 0;
}

int
split_builtin_args(char* cmd_and_args, char** argv_out)
{
	int count = 0;
	char* tok = strtok(cmd_and_args, " ");

	while (tok != NULL && count < MAX_ARGS - 1)
	{
		argv_out[count] = tok;
		count++;
		tok = strtok(NULL, " ");
	}
	argv_out[count] = NULL;
	return count;
}

int
sish_echo(char** token_args, int token_args_count)
{
	for (int i = 1; i < token_args_count; i++)
	{
		char* word = token_args[i];

		/* handled elsewhere */
		if (IS_SHELL_SPECIAL(word))
		{
			break;
		}

		printf("%s", word);


		// join with a space if not last or a shell special
		if (i < token_args_count - 1 && !IS_SHELL_SPECIAL(token_args[i + 1]))
		{
			printf(" ");
		}
	}

	printf("\n");
	return 0;
}

void
sish_exit(int status)
{
	exit(status);
}

int
sish_cd(char** token_args, int token_args_count)
{
	if (token_args_count > 2)
	{
		fprintf(stderr, "%s: cd: too many arguments.\n", GET_PROGNAME_ERR);
		return 1;
	}

	const char* target = NULL;

	/* cd or cd ~. home directory*/
	if (token_args_count == 1 || strcmp(token_args[1], "~") == 0)
	{
		target = getenv("HOME");
		if (target == NULL)
		{
			struct passwd* pw = getpwuid(getuid());
			if (pw == NULL)
			{
				fprintf(
					stderr,
					"%s: cd: cannot change directory to %s: getpwuid: %s.\n",
					GET_PROGNAME_ERR, token_args[1], strerror(errno));
				return 1;
			}
			target = pw->pw_dir;
		}
	}
	else
	{
		/* try whatever the user gave us */
		target = token_args[1];
	}

	if (chdir(target) == -1)
	{
		fprintf(stderr, "%s: cd: cannot change directory to %s: %s.\n",
		        GET_PROGNAME_ERR, target, strerror(errno));
		return 1;
	}

	return 0;
}