import type { GreaterThan } from "../greater-than.mjs";
import type { LessThan } from "../less-than.mjs";
import type { NegativeInfinity, PositiveInfinity } from "../numeric.mjs";
import type { UnknownArray } from "../unknown-array.mjs";
/**
Infer the length of the given tuple `<T>`.

Returns `never` if the given type is an non-fixed-length array like `Array<string>`.

@example
```
type Tuple = TupleLength<[string, number, boolean]>;
//=> 3

type Array = TupleLength<string[]>;
//=> never

// Supports union types.
type Union = TupleLength<[] | [1, 2, 3] | Array<number>>;
//=> 1 | 3
```

@group type-fest
*/
export type TupleLength<T extends UnknownArray> = T extends unknown ? number extends T["length"] ? never : T["length"] : never;
/**
Create a tuple type of the given length `<L>` and fill it with the given type `<Fill>`.

If `<Fill>` is not provided, it will default to `unknown`.

@link https://itnext.io/implementing-arithmetic-within-typescripts-type-system-a1ef140a6f6f

@group type-fest
*/
export type BuildTuple<
	L extends number,
	Fill = unknown,
	T extends readonly unknown[] = []
> = number extends L ? Fill[] : L extends T["length"] ? T : BuildTuple<L, Fill, [...T, Fill]>;
/**
Returns the maximum value from a tuple of integers.

Note:
- Float numbers are not supported.

@example
```
ArrayMax<[1, 2, 5, 3]>;
//=> 5

ArrayMax<[1, 2, 5, 3, 99, -1]>;
//=> 99
```

@group type-fest
*/
export type TupleMax<
	A extends number[],
	Result extends number = NegativeInfinity
> = number extends A[number] ? never : A extends [infer F extends number, ...infer R extends number[]] ? GreaterThan<F, Result> extends true ? TupleMax<R, F> : TupleMax<R, Result> : Result;
/**
Returns the minimum value from a tuple of integers.

Note:
- Float numbers are not supported.

@example
```
ArrayMin<[1, 2, 5, 3]>;
//=> 1

ArrayMin<[1, 2, 5, 3, -5]>;
//=> -5
```

@group type-fest
*/
export type TupleMin<
	A extends number[],
	Result extends number = PositiveInfinity
> = number extends A[number] ? never : A extends [infer F extends number, ...infer R extends number[]] ? LessThan<F, Result> extends true ? TupleMin<R, F> : TupleMin<R, Result> : Result;
