/**
 * # Observable aRRAY
 *
 * this is module have a collection of class and functions to help with list
 * with tasks like events, binds, subgroups and tags
 *
 * @module
 */
import type { EventObject, EventTargetCallback, Options } from "./event.js";
import type { G } from "./galho.js";
import type { Dic, Key, bool, int, str } from "./util.js";
type CalcOptions = {
    vars: Dic;
};
type Exp = {
    calc(opts: CalcOptions): any;
};
export interface Tag<T = any> {
    /**value */
    v: T;
    /**index */
    i: number;
    replace: bool;
}
export interface ListPlaceEvent<T> {
    old: int;
    new: int;
    item: T;
}
export type UpdateEvent<T> = {
    tp: "push";
    items: T[];
    start: int;
} | {
    tp: "pop";
    items: T[];
    start: int;
} | {
    tp: "place";
} | {
    tp: "edit";
} | {
    tp: "set";
    items: T[];
    removed: T[];
} | {
    tp: "tag";
    tag: str;
    newI: number;
    oldI: number;
} | {
    tp: "reload";
    start: int;
    items: T[];
};
export interface EventMap<T> extends Dic<any[]> {
    update: [UpdateEvent<T>];
    push: [T[]];
    edit: [EditEvent<T>[]];
    pop: [T[]];
    place: [ListPlaceEvent<T>];
}
export interface ListEditItem<T = Dic> {
    item: Key | T;
    props: Partial<T>;
}
export interface EditEvent<T = Dic> {
    item: T;
    props: Partial<T>;
}
type Parse<T, A> = (this: L<T, A>, value: T | A, index: number) => void | T;
export type IList<T, A = T> = {
    key?: keyof T;
    child?: str;
    parse?: Parse<T, A>;
    /**@deprecated */
    converter?: Parse<T, A>;
    g?: str[];
    sorts?: Exp[];
    clear?: bool;
} | Parse<T, A>;
/**
 * An Array with suport for events, binds, subgroups and tags
 * @template T type of element this array store
 * @template A type of element this array accept
 */
export declare class L<T = any, A = T, K extends keyof T = any> extends Array<T> implements EventObject<EventMap<T>> {
    put(start: number, ...values: Array<T | A>): this;
    removeAt(start: number, length?: number): T[];
    push(...values: Array<T | A>): number;
    pop(): T;
    shift(): T;
    unshift(...values: Array<T | A>): number;
    /**
     * clear array and insert new elements
     * @param values
     */
    set(values?: Array<T | A>): this;
    has(id: T[K], fromIndex?: number): boolean;
    includes(searchElement: T[K], fromIndex?: number): boolean;
    includes(searchElement: T, fromIndex?: number): boolean;
    addGroup(key: str): Group<T, K>;
    /**
     * get a group from id if it not exist create new
     */
    group(key: str): Group<T, K>;
    on(callback: EventTargetCallback<L<T, A>, [UpdateEvent<T>]>): L<T, A>;
    on<K extends keyof EventMap<T>>(event: K, callback: EventTargetCallback<this, EventMap<T>[K]>, options?: Options): this;
    find<S extends T>(predicate: (value: T, index: number, obj: T[]) => value is S, thisArg?: any): S | undefined;
    find(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): T | undefined;
    find(key: T | T[K]): T | undefined;
    findIndex(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): number;
    findIndex(key: T | K): number;
    sort(compareFn?: (a: T, b: T) => number): this;
    remove(...items: (K | T)[]): this;
    place(item: K | T, newIndex: number): this;
    /**get tag */
    tag(key: str): T;
    /**set tag */
    tag(key: str, value: T | K, replace?: bool): this;
    /**remove tag */
    tag(key: str, value: null): this;
    /**reload tag */
    retag(k: str, o?: int): void;
    ontag(key: str, callback: (this: L<T, A>, e: T | undefined) => any): this;
    unbind(s: G): this;
    bind<TS extends G = G>(s: TS, opts?: LBond<T, A, TS>): TS;
    bind<TS extends G = G>(s: TS, opts?: LBondInsert<T, A, TS>): TS;
    reload(item: T | K): this;
    /** volta a chamar o bind do elemento */
    reloadAt(index: int): this;
    reloadAll(): this;
    /**events handlers*/
    eh: {
        [P in keyof EventMap<T>]?: EventTargetCallback<this, EventMap<T>[P]>[];
    };
    /**when true this List do not raise events */
    slip?: bool;
    tags?: Dic<Tag<T>>;
    sorts?: Exp[];
    /**groups */
    g: Dic<Group<T, K>>;
    /**no update */
    nu?: bool;
    key?: K;
    childKey?: str;
    parse?: Parse<T, A>;
    binds?: [s: G, fn: Function][];
}
export type Alias<T = any, A = T> = Array<T | A> | L<T, A>;
export declare function copy<S>(src: L<S, any>, dest: L<S, any>, fill?: bool): void;
export declare function copy<S, D, A = D>(src: L<S, any>, dest: L<D, A>, fill: bool, parse: (value: S, index: number) => D | A): void;
export declare function tryPush<T, A = T>(l: L<T, A>, item: T): void;
/**
 * edit properties of an element of collection
 * @param item
 * @param prop
 * @param value
 */
export declare function edit<T, A = T>(l: L<T, A>, item: ListEditItem<T>): L<T, A>;
export declare function editItems<T, A = T>(l: L<T, A>, ...items: T[]): L<T, A>;
export type LBondInsert<T, A = T, TS extends G = G> = (this: L<T, A>, value: T, index?: number, container?: TS) => any;
export interface LBond<T = any, A = T, TS extends G = G> {
    /**
     * metodo que sera chamado no clear, caso n�ot tenha removera um item de cada vez*/
    clear?: false | ((container: G) => void);
    /**inset an element in arbitrary position
     se retornar um valor inserira este elemento n�o posi��o do item adicionado*/
    insert?: LBondInsert<T, A, TS>;
    reload?: (this: L<T, A>, value: T, index?: number, container?: TS) => any;
    /**
     * remove an arbitrary element
     * se retornar true remove o item naquela posi��o
     * se não definido remove o item automaticamente
     * @param this
     * @param pos
     */
    remove?: (this: L<T, A>, item: T, index: number, container?: TS) => true | void;
    /**
     *
     * @param this
     * @param value
     * @param props
     * @param container
     */
    edit?: (this: L<T, A>, item: T, index: number, props: Partial<T>, container: G) => G | void;
    /**chamado quando tenta se reposicionar um elemento */
    place?: (this: L<T, A>, oldPlace: number, newPlace: number, container: TS) => bool | void;
    /**
     *
     * @param this
     * @param empty
     * @param container
     */
    empty?: (this: L<T, A>, empty: bool, container?: TS) => any;
    /**
     * */
    groups?: Dic<GroupBind<T, A, TS>> | GroupBind<T, A, TS>;
    /** */
    tag?: (this: L<T, A>, active: bool, index: number, parent: TS, tag: str, value: T) => void;
}
export declare function extend<T = any, A = T>(l?: Alias<T, A>, opts?: IList<T, A>): L<T, A, any>;
export declare function orray<T = any, A = T>(options: IList<T, A>): L<T, A>;
export declare function orray<T = any, A = T>(array?: L<T, A>, options?: Parse<T, A>): L<T, A>;
export declare function orray<T = any, A = T>(array?: Alias<T, A>, options?: IList<T, A>): L<T, A>;
export default orray;
interface GroupEvents<T = any> extends Dic<any[]> {
    push: [T[]];
    remove: [T[]];
    set: GroupSetEvent<T>;
}
export type GroupSetEvent<T> = [add?: T[], addId?: int[], remove?: T[], removeId?: int[]];
export declare class Group<T, K extends keyof T> extends Array<T> implements EventObject<GroupEvents<T>> {
    eh: {
        [P in keyof GroupEvents<T>]?: EventTargetCallback<this, GroupEvents<T>[P]>[];
    };
    slip?: boolean;
    /**no update */
    nu?: boolean;
    l: L<T, any>;
    push(...items: (T | K)[]): number;
    toggle(item: T): void;
    pushRange(start: int, end: int): number[];
    pushAll(): number[];
    remove(...items: T[]): int[];
    removeAt(index: number, count?: number): void;
    clear(): number[];
    removeRange(from: number, to?: number): number[];
    set(add: (T | K)[]): this;
    invert(): this;
    setRange(start: number, end: number): void;
    indexes(): number[];
    keyField(): K[];
    /**on update */
    on(callback: EventTargetCallback<Group<T, K>, GroupSetEvent<T>>): this;
    reload(v: T, i?: number): this;
    static get [Symbol.species](): ArrayConstructor;
}
export type GroupBind<T, A = T, TS extends G = G> = (this: L<T, A>, state: boolean, index: number, parent: TS, groupKey: string, item: T) => void;
export declare function bind<T, A = T, TS extends G = G>(l: L<T, A>, s: TS, groupKey: string, bond: GroupBind<T, A, TS>): TS;
export declare namespace range {
    type Tp = "set" | "add" | "range" | "addR";
    function pivot<T, A = T>(l: L<T, A>, tag: str): number;
    function add<T, A = T>(l: L<T, A>, key: str, value: T | int | str, tp: Tp): L<T, A, any>;
    /**select all elements */
    function addAll<T, A = T>(l: L<T, A>, tag: str): L<T, A, any>;
    /** remove focus */
    function clear<T, A = T>(l: L<T, A>, tag: str): L<T, A, any>;
    function onchange<T, A = T, K extends keyof T = any>(l: L<T, A>, tag: str, listener?: (this: L<T, A>, active: T, selected?: Group<T, K>) => void): L<T, A, any>;
    /**select type */
    const tp: (control: boolean, shift: boolean) => Tp;
    function move(l: L, tag: str, distance: number, tp: Tp): L<any, any, any>;
    function movePivot(l: L, tag: str, distance: number, revert?: boolean): L<any, any, any>;
    function list<T, A = T>(l: L<T, A>, key: str): T[];
}
