///////////////////////////////////////////////////////////////////////////////
//
/// \file       options.c
/// \brief      Parser for filter-specific options
//
//  Author:     Lasse Collin
//
//  This file has been put into the public domain.
//  You can do whatever you want with this file.
//
///////////////////////////////////////////////////////////////////////////////

#include "private.h"


///////////////////
// Generic stuff //
///////////////////

typedef struct {
	const char *name;
	uint64_t id;
} name_id_map;


typedef struct {
	const char *name;
	const name_id_map *map;
	uint64_t min;
	uint64_t max;
} option_map;


/// Parses option=value pairs that are separated with commas:
/// opt=val,opt=val,opt=val
///
/// Each option is a string, that is converted to an integer using the
/// index where the option string is in the array.
///
/// Value can be
///  - a string-id map mapping a list of possible string values to integers
///    (opts[i].map != NULL, opts[i].min and opts[i].max are ignored);
///  - a number with minimum and maximum value limit
///    (opts[i].map == NULL && opts[i].min != UINT64_MAX);
///  - a string that will be parsed by the filter-specific code
///    (opts[i].map == NULL && opts[i].min == UINT64_MAX, opts[i].max ignored)
///
/// When parsing both option and value succeed, a filter-specific function
/// is called, which should update the given value to filter-specific
/// options structure.
///
/// \param      str     String containing the options from the command line
/// \param      opts    Filter-specific option map
/// \param      set     Filter-specific function to update filter_options
/// \param      filter_options  Pointer to filter-specific options structure
///
/// \return     Returns only if no errors occur.
///
static void
parse_options(const char *str, const option_map *opts,
		void (*set)(void *filter_options,
			uint32_t key, uint64_t value, const char *valuestr),
		void *filter_options)
{
	if (str == NULL || str[0] == '\0')
		return;

	char *s = xstrdup(str);
	char *name = s;

	while (*name != '\0') {
		if (*name == ',') {
			++name;
			continue;
		}

		char *split = strchr(name, ',');
		if (split != NULL)
			*split = '\0';

		char *value = strchr(name, '=');
		if (value != NULL)
			*value++ = '\0';

		if (value == NULL || value[0] == '\0')
			message_fatal(_("%s: Options must be `name=value' "
					"pairs separated with commas"), str);

		// Look for the option name from the option map.
		size_t i = 0;
		while (true) {
			if (opts[i].name == NULL)
				message_fatal(_("%s: Invalid option name"),
						name);

			if (strcmp(name, opts[i].name) == 0)
				break;

			++i;
		}

		// Option was found from the map. See how we should handle it.
		if (opts[i].map != NULL) {
			// value is a string which we should map
			// to an integer.
			size_t j;
			for (j = 0; opts[i].map[j].name != NULL; ++j) {
				if (strcmp(opts[i].map[j].name, value) == 0)
					break;
			}

			if (opts[i].map[j].name == NULL)
				message_fatal(_("%s: Invalid option value"),
						value);

			set(filter_options, i, opts[i].map[j].id, value);

		} else if (opts[i].min == UINT64_MAX) {
			// value is a special string that will be
			// parsed by set().
			set(filter_options, i, 0, value);

		} else {
			// value is an integer.
			const uint64_t v = str_to_uint64(name, value,
					opts[i].min, opts[i].max);
			set(filter_options, i, v, value);
		}

		// Check if it was the last option.
		if (split == NULL)
			break;

		name = split + 1;
	}

	free(s);
	return;
}


///////////
// Delta //
///////////

enum {
	OPT_DIST,
};


static void
set_delta(void *options, uint32_t key, uint64_t value,
		const char *valuestr lzma_attribute((__unused__)))
{
	lzma_options_delta *opt = options;
	switch (key) {
	case OPT_DIST:
		opt->dist = value;
		break;
	}
}


extern lzma_options_delta *
options_delta(const char *str)
{
	static const option_map opts[] = {
		{ "dist",     NULL,  LZMA_DELTA_DIST_MIN,
		                     LZMA_DELTA_DIST_MAX },
		{ NULL,       NULL,  0, 0 }
	};

	lzma_options_delta *options = xmalloc(sizeof(lzma_options_delta));
	*options = (lzma_options_delta){
		// It's hard to give a useful default for this.
		.type = LZMA_DELTA_TYPE_BYTE,
		.dist = LZMA_DELTA_DIST_MIN,
	};

	parse_options(str, opts, &set_delta, options);

	return options;
}


/////////
// BCJ //
/////////

enum {
	OPT_START_OFFSET,
};


static void
set_bcj(void *options, uint32_t key, uint64_t value,
		const char *valuestr lzma_attribute((__unused__)))
{
	lzma_options_bcj *opt = options;
	switch (key) {
	case OPT_START_OFFSET:
		opt->start_offset = value;
		break;
	}
}


extern lzma_options_bcj *
options_bcj(const char *str)
{
	static const option_map opts[] = {
		{ "start",    NULL,  0, UINT32_MAX },
		{ NULL,       NULL,  0, 0 }
	};

	lzma_options_bcj *options = xmalloc(sizeof(lzma_options_bcj));
	*options = (lzma_options_bcj){
		.start_offset = 0,
	};

	parse_options(str, opts, &set_bcj, options);

	return options;
}


//////////
// LZMA //
//////////

enum {
	OPT_PRESET,
	OPT_DICT,
	OPT_LC,
	OPT_LP,
	OPT_PB,
	OPT_MODE,
	OPT_NICE,
	OPT_MF,
	OPT_DEPTH,
};


static void lzma_attribute((__noreturn__))
error_lzma_preset(const char *valuestr)
{
	message_fatal(_("Unsupported LZMA1/LZMA2 preset: %s"), valuestr);
}


static void
set_lzma(void *options, uint32_t key, uint64_t value, const char *valuestr)
{
	lzma_options_lzma *opt = options;

	switch (key) {
	case OPT_PRESET: {
		if (valuestr[0] < '0' || valuestr[0] > '9')
			error_lzma_preset(valuestr);

		uint32_t preset = valuestr[0] - '0';

		// Currently only "e" is supported as a modifier,
		// so keep this simple for now.
		if (valuestr[1] != '\0') {
			if (valuestr[1] == 'e')
				preset |= LZMA_PRESET_EXTREME;
			else
				error_lzma_preset(valuestr);

			if (valuestr[2] != '\0')
				error_lzma_preset(valuestr);
		}

		if (lzma_lzma_preset(options, preset))
			error_lzma_preset(valuestr);

		break;
	}

	case OPT_DICT:
		opt->dict_size = value;
		break;

	case OPT_LC:
		opt->lc = value;
		break;

	case OPT_LP:
		opt->lp = value;
		break;

	case OPT_PB:
		opt->pb = value;
		break;

	case OPT_MODE:
		opt->mode = value;
		break;

	case OPT_NICE:
		opt->nice_len = value;
		break;

	case OPT_MF:
		opt->mf = value;
		break;

	case OPT_DEPTH:
		opt->depth = value;
		break;
	}
}


extern lzma_options_lzma *
options_lzma(const char *str)
{
	static const name_id_map modes[] = {
		{ "fast",   LZMA_MODE_FAST },
		{ "normal", LZMA_MODE_NORMAL },
		{ NULL,     0 }
	};

	static const name_id_map mfs[] = {
		{ "hc3", LZMA_MF_HC3 },
		{ "hc4", LZMA_MF_HC4 },
		{ "bt2", LZMA_MF_BT2 },
		{ "bt3", LZMA_MF_BT3 },
		{ "bt4", LZMA_MF_BT4 },
		{ NULL,  0 }
	};

	static const option_map opts[] = {
		{ "preset", NULL,   UINT64_MAX, 0 },
		{ "dict",   NULL,   LZMA_DICT_SIZE_MIN,
				(UINT32_C(1) << 30) + (UINT32_C(1) << 29) },
		{ "lc",     NULL,   LZMA_LCLP_MIN, LZMA_LCLP_MAX },
		{ "lp",     NULL,   LZMA_LCLP_MIN, LZMA_LCLP_MAX },
		{ "pb",     NULL,   LZMA_PB_MIN, LZMA_PB_MAX },
		{ "mode",   modes,  0, 0 },
		{ "nice",   NULL,   2, 273 },
		{ "mf",     mfs,    0, 0 },
		{ "depth",  NULL,   0, UINT32_MAX },
		{ NULL,     NULL,   0, 0 }
	};

	lzma_options_lzma *options = xmalloc(sizeof(lzma_options_lzma));
	if (lzma_lzma_preset(options, LZMA_PRESET_DEFAULT))
		message_bug();

	parse_options(str, opts, &set_lzma, options);

	if (options->lc + options->lp > LZMA_LCLP_MAX)
		message_fatal(_("The sum of lc and lp must not exceed 4"));

	const uint32_t nice_len_min = options->mf & 0x0F;
	if (options->nice_len < nice_len_min)
		message_fatal(_("The selected match finder requires at "
				"least nice=%" PRIu32), nice_len_min);

	return options;
}
