/* See LICENSE file for copyright and license details. */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include "util.h"

static int itostr(char *, int, int);
static FILE *nextfile(FILE *, char *, int, int);

static void
usage(void)
{
	eprintf("usage: split [-d] [-a len] [-b [bytes[k|m|g]]] [-l [lines]] [input [prefix]]\n");
}

static int base = 26, start = 'a';

int
main(int argc, char *argv[])
{
	int plen, slen = 2;
	int ch;
	char name[NAME_MAX+1];
	char *prefix = "x";
	char *file = NULL;
	char *tmp, *end;
	uint64_t size = 1000, scale = 1, n;
	int always = 0;
	FILE *in = stdin, *out = NULL;

	ARGBEGIN {
	case 'b':
		always = 1;
		tmp = ARGF();
		if(tmp == NULL)
			break;

		size = strtoull(tmp, &end, 10);
		if(*end == '\0')
			break;
		switch(toupper((int)*end)) {
		case 'K':
			scale = 1024;
			break;
		case 'M':
			scale = 1024L * 1024L;
			break;
		case 'G':
			scale = 1024L * 1024L * 1024L;
			break;
		default:
			usage();
		}
		if(size > (UINT64_MAX/scale))
			eprintf("'%s': out of range\n", tmp);
		size *= scale;
		break;
	case 'l':
		always = 0;
		tmp = ARGF();
		if(tmp)
			size = estrtol(tmp, 10);
		break;
	case 'a':
		slen = estrtol(EARGF(usage()), 10);
		break;
	case 'd':
		base = 10;
		start = '0';
		break;
	default:
		usage();
	} ARGEND;

	if(*argv)
		file = *argv++;
	if(*argv)
		prefix = *argv++;
	if(*argv)
		usage();

	plen = strlen(prefix);
	if(plen+slen > NAME_MAX)
		eprintf("names cannot exceed %d bytes\n", NAME_MAX);
	strlcpy(name, prefix, sizeof(name));

	if(file && strcmp(file, "-") != 0) {
		in = fopen(file, "r");
		if(!in)
			eprintf("'%s':", file);
	}

Nextfile:
	while((out = nextfile(out, name, plen, slen))) {
		n = 0;
		while((ch = getc(in)) != EOF) {
			putc(ch, out);
			n += (always || ch == '\n');
			if(n >= size)
				goto Nextfile;
		}
		fclose(out);
		break;
	}
	return EXIT_SUCCESS;
}

int
itostr(char *str, int x, int n)
{
	str[n] = '\0';
	while(n-- > 0) {
		str[n] = start + (x % base);
		x /= base;
	}
	if(x)
		return -1;
	return 0;
}

FILE *
nextfile(FILE *f, char *buf, int plen, int slen)
{
	static int n = 0;
	int s;

	if(f)
		fclose(f);
	s = itostr(buf+plen, n++, slen);
	if(s == -1)
		return NULL;

	f = fopen(buf, "w");
	if(!f)
		eprintf("'%s':", buf);
	return f;
}