import { ReadonlyTuple, Tuple, RandomObjParam } from '../utils.js';
import '@gouvernathor/rng';

/**
 * A set of opinions represented as a multi-dimensional vector of integers,
 * with each dimension (each vector member) representing one subject on which
 * an opinion is held.
 * The value in each dimension can be symmetrically positive or negative.
 * Values close to 0 represent neutrality or indecision.
 * The type parameter should be a number giving the number of opinions,
 * of elements in the array.
 * The range of values in the array is from -opinMax to +opinMax,
 * inclusive, as provided to the OpinionsArrayManager object.
 */
type OpinionsArray<N extends number> = Tuple<number, N>;
/**
 * Returns a one-dimensional alignment of the opinions.
 *
 * @param opinions array of opinions
 * @returns a value such that if each opinion, in each member of a pool
 * of Opinionated instances, is generated randomly following an integer uniform distribution,
 * the return value of this function follows a uniform distribution.
 * With the default factors, the return value is between 0 and 1,
 * and is increasing with each separate opinion,
 * with opinions having a decreasing importance as the array goes.
 */
interface Aligner<N extends number> {
    (opinions: Readonly<OpinionsArray<N>>): number;
}
/**
 * This holds the parameters for the opinions arrays : their length,
 * their range of values, and how to align them to one dimension.
 *
 * It can be seen as a metaclass for the opinions arrays, except that
 * they are real arrays instead of a custom type, so this is a normal class.
 *
 * There should generally be only one instance of this class per system,
 * and all opinions arrays should share the same parameters -
 * at least the same length and value range - even for opinions of different kinds,
 * for instance parties, citizens, and bills.
 * In any case, disagreement should not pe supported between subclasses
 * of different nOpinions or opinMax values.
 *
 * Other than being a repository for the meta parameters,
 * this class provides :
 * - a balanced single-dimensional alignment for all opinions arrays
 * - a random generator for the opinions arrays
 */
declare class OpinionsArrayManager<N extends number> {
    /**
     * The number of opinions in each array, equal to the type parameter,
     * provided for runtime access.
     */
    readonly nOpinions: N;
    /**
     * The maximum possible value of each opinion in the array.
     */
    readonly opinMax: number;
    readonly opinionAlignmentFactors: ReadonlyTuple<N, number>;
    /**
     * This function takes an opinions array and returns a single value
     * representing the alignment of this set of opinions in a single axis.
     * If using the default opinion alignment factors, the alignment is between 0 and 1.
     */
    readonly aligner: Aligner<N>;
    /**
     * A random generator for the opinions arrays.
     * You can pass a random object generator, or a seed that will be used
     * to initialize a random object.
     *
     * Each opinion value in the array will be generated following a uniform law.
     */
    readonly generator: (p?: RandomObjParam) => OpinionsArray<N>;
    constructor({ nOpinions, opinMax, opinionAlignmentFactors }: {
        nOpinions: N;
        opinMax: number;
        opinionAlignmentFactors?: ReadonlyTuple<N, number>;
    });
}

export { type Aligner, type OpinionsArray, OpinionsArrayManager };
