/**
 * \file ui-entry-combiner.h
 * \brief Declare lookup and access to algorithms for combining property values
 */
#ifndef INCLUDED_UI_ENTRY_COMBINER_H
#define INCLUDED_UI_ENTRY_COMBINER_H

#include "h-basic.h"

/**
 * This is the value used in val, aux_vals, or in accumulated results when
 * the real value is unknown to the player.
 */
#define UI_ENTRY_UNKNOWN_VALUE (INT_MAX)

/**
 * This is the value used in vals, aux_vals, or in accumulated results when
 * the value is to be treated as not present.
 */
#define UI_ENTRY_VALUE_NOT_PRESENT (INT_MAX - 1)

/**
 * This is the value used in vals, aux_vals, or in accumulated results for
 * Angband elemental resistances when something provides a vulnerability and
 * resistance to the same element but does not provide an immunity to that
 * element.
 */
#define UI_ENTRY_RESIST0_RES_VUL (INT_MAX - 2)

struct ui_entry_combiner_state {
	void *work;
	int accum;
	int accum_aux;
};

/**
 * There are two ways to use the combiner.  With one, you declare a struct
 * ui_entry_combiner_state, pass it and the initial value and initial
 * auxiliary value to *init_func, pass each subsequent value and auxiliary
 * value along with the combiner state structure to *accum_func, and then call
 * *finish_func to complete the process leaving the combined value in the
 * accum field of the state structure and the combined auxiliary value in the
 * accum_aux field of the state structure.
 *
 * The second way assumes you have the values and auxiliary values to be
 * combined stored in arrays, then you can call *vec_func with those arrays to
 * get the result.
 *
 * How auxiliary values are used and interpreted varies.  There's two current
 * uses for them.  One is to store the time-dependent effect while the value
 * stores the permanent effect.  The other is to store the sustain flag while
 * the value holds the corresponding stat modifier.
 *
 * All the functions treat values equal to UI_ENTRY_UNKNOWN (value is not
 * known to the player) or UI_ENTRY_VALUE_NOT_PRESENT (no value, for instance
 * because of absent equipment) as special cases.  Functions for combining
 * elemental resistances will treat UI_ENTRY_RESIST0_RES_VUL (the value
 * represents something that provides a resistance, a vulnerability, but not
 * an immunity to the same element) as a special case.
 */
struct ui_entry_combiner_funcs {
	void (*init_func)(int v, int a, struct ui_entry_combiner_state *st);
	void (*accum_func)(int v, int a, struct ui_entry_combiner_state *st);
	void (*finish_func)(struct ui_entry_combiner_state *st);
	void (*vec_func)(int n, const int *vals, const int *auxs, int *accum, int *accum_aux);
};

int ui_entry_combiner_lookup(const char *name);
int ui_entry_combiner_get_funcs(int ind, struct ui_entry_combiner_funcs *funcs);
#endif /* INCLUDED_UI_ENTRY_COMBINER_H */
