/** @internal NOTE: Internal APIs. Subject to change. Use of these APIs in production applications is not supported. */ /** */

export type Writeable<T> = { -readonly [K in keyof T]: T[K] };

/**
 * Typesafe way to cast object as writeable
 * @param o Object to cast to writeable
 * @returns writeable.
 */
export function asWriteable<T>(o: T): DeepMutable<T> {
    return o as DeepMutable<T>;
}

/**
 * Bound is an array containing 6 numbers. [minX, minY, minZ, maxX, maxY, maxZ]
 * First 3 is the xyz for minimum coordinate position.
 * Last 3 is the xyz for maximum coordinate position.
 */
export type Bound = [number, number, number, number, number, number];

/**
 * Direction to zoom. -1 = out, 1 = in, 0 = nothing
 */
export type ZoomDirection = -1 | 0 | 1;

/**
 * Copy a type but make some of the properties optional.
 */
export type CopyWithPartialProperties<T, K extends keyof T> = Omit<T, K> & Partial<T>;

/**
 * Adds a `type` field to a type. Useful when creating discriminant union types.
 * ```typescript
 * type Base = { data: string };
 * type MyUnion = Discriminant<Base, 'base64'> | Discriminant<Base, 'hex'>;
 * const base64: MyUnion = { data: 'aGVsbG8=', type: 'base64' };
 * if (base64.type === 'base64') {
 *    console.log(base64.data);
 * }
 * ```
 */
export type AddTypeDiscriminant<T, K extends string | number | symbol> = T & { type: K };

/**
 * Type modifier to make all the properties of an object mutable recursively. Basically the reverse
 * of BabylonJS's `DeepImmutable` type.
 */

// eslint-disable-next-line @typescript-eslint/ban-types
export type DeepMutable<T> = T extends undefined | null | boolean | string | number | Function | Element
    ? T
    : T extends Array<infer U>
      ? DeepMutableArray<U>
      : /* T extends Map<infer K, infer V> ? DeepMutableMap<K, V> : // es2015+ only */
        DeepMutableObject<T>;

/**
 * Type modifier to make object properties mutable.
 */
export type DeepMutableObject<T> = { -readonly [K in keyof T]: DeepMutable<T[K]> };

/** @internal */
type DeepMutableArray<T> = Array<DeepMutable<T>>;
/** @internal */
/* interface DeepMutableMap<K, V> extends Map<DeepMutable<K>, DeepMutable<V>> {} // es2015+ only */
