/*
 * Copyright (C) 2010-2014 Karel Zak <kzak@redhat.com>
 *
 * This file may be redistributed under the terms of the
 * GNU Lesser General Public License.
 */
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <getopt.h>

#include "c.h"
#include "nls.h"
#include "strutils.h"

#include "libsmartcols.h"

static int add_children(struct libscols_table *tb,
			struct libscols_line *ln, int fd);


enum { COL_MODE, COL_SIZE, COL_NAME };

/* add columns to the @tb */
static void setup_columns(struct libscols_table *tb, int notree)
{
	if (!scols_table_new_column(tb, "MODE", 0.3, 0))
		goto fail;
	if (!scols_table_new_column(tb, "SIZE", 5, SCOLS_FL_RIGHT))
		goto fail;
	if (!scols_table_new_column(tb, "NAME", 0.5,
			(notree ? 0 : SCOLS_FL_TREE) | SCOLS_FL_NOEXTREMES))
		goto fail;

	return;
fail:
	scols_unref_table(tb);
	err(EXIT_FAILURE, "failed to create output columns");
}

/* add a new line to @tb, the content is based on @st */
static int add_line_from_stat(struct libscols_table *tb,
			      struct libscols_line *parent,
			      int parent_fd,
			      struct stat *st,
			      const char *name)
{
	struct libscols_line *ln;
	char modbuf[11], *p;
	mode_t mode = st->st_mode;
	int rc = 0;

	ln = scols_table_new_line(tb, parent);
	if (!ln)
		err(EXIT_FAILURE, "failed to create output line");

	/* MODE; local buffer, use scols_line_set_data() that calls strdup() */
	xstrmode(mode, modbuf);
	if (scols_line_set_data(ln, COL_MODE, modbuf))
		goto fail;

	/* SIZE; already allocated string, use scols_line_refer_data() */
	p = size_to_human_string(0, st->st_size);
	if (!p || scols_line_refer_data(ln, COL_SIZE, p))
		goto fail;

	/* NAME */
	if (scols_line_set_data(ln, COL_NAME, name))
		goto fail;

	/* colors */
	if (scols_table_colors_wanted(tb)) {
		struct libscols_cell *ce = scols_line_get_cell(ln, COL_NAME);

		if (S_ISDIR(mode))
			scols_cell_set_color(ce, "blue");
		else if (S_ISLNK(mode))
			scols_cell_set_color(ce, "cyan");
		else if (S_ISBLK(mode))
			scols_cell_set_color(ce, "magenta");
		else if ((mode & S_IXOTH) || (mode & S_IXGRP) || (mode & S_IXUSR))
			scols_cell_set_color(ce, "green");
	}

	if (S_ISDIR(st->st_mode)) {
		int fd;

		if (parent_fd >= 0)
			fd = openat(parent_fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC);
		else
			fd = open(name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC);
		if (fd >= 0) {
			rc = add_children(tb, ln, fd);
			close(fd);
		}
	}
	return rc;
fail:
	err(EXIT_FAILURE, "failed to create cell data");
	return -1;
}

/* read all entries from directory addressed by @fd */
static int add_children(struct libscols_table *tb,
			struct libscols_line *ln,
			int fd)
{
	DIR *dir;
	struct dirent *d;

	dir = fdopendir(fd);
	if (!dir)
		return -errno;

	while ((d = readdir(dir))) {
		struct stat st;

		if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0)
			continue;
		if (fstatat(fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW) != 0)
			continue;
		add_line_from_stat(tb, ln, fd, &st, d->d_name);
	}
	closedir(dir);
	return 0;
}

static void add_lines(struct libscols_table *tb, const char *dirname)
{
	struct stat st;

	if (lstat(dirname, &st))
		err(EXIT_FAILURE, "%s", dirname);

	add_line_from_stat(tb, NULL, -1, &st, dirname);
}

static void __attribute__((__noreturn__)) usage(FILE *out)
{
	fprintf(out, " %s [options] [<dir> ...]\n\n", program_invocation_short_name);
	fputs(" -c, --csv               display a csv-like output\n", out);
	fputs(" -i, --ascii             use ascii characters only\n", out);
	fputs(" -l, --list              use list format output\n", out);
	fputs(" -n, --noheadings        don't print headings\n", out);
	fputs(" -p, --pairs             use key=\"value\" output format\n", out);
	fputs(" -J, --json              use JSON output format\n", out);
	fputs(" -r, --raw               use raw output format\n", out);
	fputs(" -S, --range-start <n>   first line to print\n", out);
	fputs(" -E, --range-end <n>     last line to print\n", out);

	exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}

int main(int argc, char *argv[])
{
	struct libscols_table *tb;
	int c, notree = 0, nstart = -1, nend = -1;


	static const struct option longopts[] = {
		{ "ascii",	0, NULL, 'i' },
		{ "csv",        0, NULL, 'c' },
		{ "list",       0, NULL, 'l' },
		{ "noheadings",	0, NULL, 'n' },
		{ "pairs",      0, NULL, 'p' },
		{ "json",       0, NULL, 'J' },
		{ "raw",        0, NULL, 'r' },
		{ "range-start",1, NULL, 'S' },
		{ "range-end",  1, NULL, 'E' },
		{ NULL, 0, NULL, 0 },
	};

	setlocale(LC_ALL, "");	/* just to have enable UTF8 chars */

	scols_init_debug(0);

	tb = scols_new_table();
	if (!tb)
		err(EXIT_FAILURE, "failed to create output table");

	while((c = getopt_long(argc, argv, "ciJlnprS:E:", longopts, NULL)) != -1) {
		switch(c) {
		case 'c':
			scols_table_set_column_separator(tb, ",");
			scols_table_enable_raw(tb, 1);
			notree = 1;
			break;
		case 'i':
			scols_table_enable_ascii(tb, 1);
			break;
		case 'J':
			scols_table_set_name(tb, "scolstest");
			scols_table_enable_json(tb, 1);
			break;
		case 'l':
			notree = 1;
			break;
		case 'n':
			scols_table_enable_noheadings(tb, 1);
			break;
		case 'p':
			scols_table_enable_export(tb, 1);
			notree = 1;
			break;
		case 'r':
			scols_table_enable_raw(tb, 1);
			notree = 1;
			break;
		case 'S':
			nstart = strtos32_or_err(optarg, "failed to parse range start") - 1;
			break;
		case 'E':
			nend = strtos32_or_err(optarg, "failed to parse range end") - 1;
			break;
		default:
			usage(stderr);
		}
	}

	scols_table_enable_colors(tb, isatty(STDOUT_FILENO));
	setup_columns(tb, notree);

	if (optind == argc)
		add_lines(tb, ".");
	else while (optind < argc)
		add_lines(tb, argv[optind++]);

	if (nstart >= 0 || nend >= 0) {
		/* print subset */
		struct libscols_line *start = NULL, *end = NULL;

		if (nstart >= 0)
			start = scols_table_get_line(tb, nstart);
		if (nend >= 0)
			end = scols_table_get_line(tb, nend);

		if (start || end)
			scols_table_print_range(tb, start, end);
	} else
		/* print all table */
		scols_print_table(tb);

	scols_unref_table(tb);
	return EXIT_SUCCESS;
}
