import { Ref } from "@cfcs/core";
import Grid, { GridOptions, GridFunction, GridItem, ContainerManagerStatus, ItemRendererStatus, Methods } from "@egjs/grid";
import { GROUP_TYPE, INFINITEGRID_METHODS, ITEM_TYPE } from "./consts";
import { GroupManagerStatus } from "./GroupManager";
import InfiniteGrid from "./InfiniteGrid";
import { InfiniteGridItem } from "./InfiniteGridItem";
import { Renderer } from "./Renderer/Renderer";
import { ScrollManagerStatus } from "./ScrollManager";
/**
 * @typedef
 */
export interface InfiniteGridStatus {
    itemRenderer: ItemRendererStatus;
    containerManager: ContainerManagerStatus;
    groupManager: GroupManagerStatus;
    scrollManager: ScrollManagerStatus;
}
export interface InfiniteGridGroup {
    type: GROUP_TYPE;
    groupKey: string | number;
    grid: Grid;
    items: InfiniteGridItem[];
    renderItems: InfiniteGridItem[];
}
export interface CategorizedGroup<Item extends InfiniteGridItemInfo = InfiniteGridItem> {
    groupKey: number | string;
    items: Item[];
}
/**
 * @typedef
 */
export interface InfiniteGridItemInfo {
    type?: ITEM_TYPE;
    groupKey?: string | number;
    inserted?: boolean;
    key?: string | number;
    element?: HTMLElement | null;
    html?: string;
    data?: Record<string, any>;
    attributes?: Record<string, any>;
}
/**
 * @typedef
 * @extends Grid.GridOptions
 */
export interface InfiniteGridOptions extends GridOptions {
    /**
     * The target to which the container is applied. If false, create itself, if true, create container. A string or HTMLElement specifies the target directly.
     * @ko container를 적용할 대상. false면 자기 자신, true면 container를 생성. string 또는 HTMLElement는 직접 대상을 지정.
     * @default false
     */
    container?: boolean | HTMLElement | string | Ref<HTMLElement>;
    /**
     * If you create a container, you can set the container's tag.
     * @ko container를 생성한다면 container의 tag를 정할 수 있다.
     * @default "div"
     */
    containerTag?: string;
    /**
     * The size of the scrollable area for adding the next group of items.
     * @ko 다음 아이템 그룹을 추가하기 위한 스크롤 영역의 크기.
     * @default 100
     */
    threshold?: number;
    /**
     * Whether to show only the DOM of the visible area.
     * @ko 보이는 영역의 DOM만 보여줄지 여부.
     * @default true
     */
    useRecycle?: boolean;
    /**
     * When using `useRecycle` option, remove elements of invisible items. If you want to improve performance (memory issues), enable it.
     * @ko `useRecycle`옵션을 사용하는 경우 보이지 않는 아이템들의 element를 제거한다. 성능(메모리 이슈)을 높이고 싶다면 활성화 해라.
     * @default false
     */
    useDetachedRecycle?: boolean;
    /**
     * @default false
     */
    isReachStart?: boolean;
    /**
     * @default false
     */
    isReachEnd?: boolean;
    /**
     * You can set the scrollContainer directly. In this case, the container becomes the wrapper itself.
     * @ko scrollContainer를 직접 정할 수 있다. 이 경우 container는 wrapper 자기 자신이 된다.
     */
    scrollContainer?: HTMLElement | string | Ref<HTMLElement> | null;
    /**
     * Grid class to apply Infinite function.
     * @ko Infinite 기능을 적용할 Grid 클래스.
     */
    gridConstructor?: GridFunction;
    /**
     * A function that checks whether non-rendering items are included in the Grid.
     * @ko 렌더링 되지 않는 아이템를 Grid에 포함시킬지 체크하는 함수.
     * @private
     */
    appliedItemChecker?: (item: InfiniteGridItem, grid: Grid) => boolean;
    /**
     * class that renders the DOM.
     * @ko DOM을 렌더하는 클래스.
     * @private
     */
    renderer?: Renderer | null;
}
/**
 * @typedef
 * @property - Groups corresponding to placeholders <ko>placholder에 해당하는 그룹</ko>
 * @property - Items corresponding to placeholders <ko>placholder에 해당하는 아이템들</ko>
 * @property - Remove the inserted placeholders. <ko>추가한 placeholder들을 삭제한다.</ko>
 */
export interface InsertedPlaceholdersResult {
    group: InfiniteGridGroup;
    items: InfiniteGridItem[];
    remove(): void;
}
/**
 * @typedef
 */
export interface OnRequestAppend {
    /**
     * An InfiniteGrid instance that triggered this event. <ko>이 이벤트를 트리거한 InfiniteGrid의 인스턴스</ko>
     */
    currentTarget: InfiniteGrid;
    /**
     * Last group key. <ko>마지막 그룹의 키.</ko>
     */
    groupKey: string | number | undefined;
    /**
     * The key of the next group that should replace Virtual Item(placeholder)s. <ko>Virtual Item(placeholder)들을 대체해야 할 다음 그룹의 키.</ko>
     */
    nextGroupKey?: string | number | undefined;
    /**
     * Array of the following group keys that need to be replaced with Virtual Item(placeholder)s.
     * <ko>Virtual Item(placeholder)들을 대체해야 할 다음 그룹키 배열.</ko>
     */
    nextGroupKeys: Array<string | number>;
    /**
     * Whether to request virtual groups corresponding to Virtual Item(placeholder)s.
     * <ko>Virtual Item(placeholder)들에 해당하는 가상의 그룹을 요청하는지 여부</ko>
     */
    isVirtual: boolean;
    /**
     * Call this when the end has been reached and there are no more groups (or items) to add. Or set the `isReachEnd` prop to true.
     * <ko>끝에 도달해서 더 이상 추가할 그룹(또는 아이템)이 없는 경우 호출해라. 또는 `isReachEnd` 옵션을 true로 설정해라.</ko>
     */
    reachEnd(): void;
    /**
     * Call this when the start has been reached and there are no more groups (or items) to add. Or set the `isReachStart` prop to true.
     * <ko>시작에 도달해서 더 이상 추가할 그룹(또는 아이템)이 없는 경우 호출해라. 또는 `isReachStart` 옵션을 true로 설정해라.</ko>
     */
    reachStart(): void;
    /**
     * Set to standby to request data. <ko>데이터를 요청하기 위해 대기 상태로 설정한다.</ko>
     */
    wait(): void;
    /**
     * When the data request is complete, it is set to ready state. <ko>데이터 요청이 끝났다면 준비 상태로 설정한다.</ko>
     */
    ready(): void;
}
/**
 * @typedef
 */
export interface OnRequestPrepend {
    /**
     * An InfiniteGrid instance that triggered this event.
     * <ko>이 이벤트를 트리거한 InfiniteGrid의 인스턴스</ko>
     */
    currentTarget: InfiniteGrid;
    /**
     * The key of the next group that should replace Virtual Item(placeholder)s.
     * <ko>Virtual Item(placeholder)들을 대체해야 할 다음 그룹의 키.</ko>
     */
    groupKey: string | number | undefined;
    /**
     * The key of the next group that should replace Virtual Item(placeholder)s.
     * <ko>Virtual Item(placeholder)들을 대체해야 할 다음 그룹의 키.</ko>
     */
    nextGroupKey?: string | number | undefined;
    /**
     * Array of the following group keys that need to be replaced with Virtual Item(placeholder)s.
     * <ko>Virtual Item(placeholder)들을 대체해야 할 다음 그룹키 배열.</ko>
     */
    nextGroupKeys: Array<string | number>;
    /**
     * Whether to request virtual groups corresponding to Virtual Item(placeholder)s.
     * <ko>Virtual Item(placeholder)들에 해당하는 가상의 그룹을 요청하는지 여부</ko>
     */
    isVirtual: boolean;
    /**
     * Call this when the end has been reached and there are no more groups (or items) to add. Or set the `isReachEnd` prop to true.
     * <ko>끝에 도달해서 더 이상 추가할 그룹(또는 아이템)이 없는 경우 호출해라. 또는 `isReachEnd` 옵션을 true로 설정해라.</ko>
     */
    reachEnd(): void;
    /**
     * Call this when the start has been reached and there are no more groups (or items) to add. Or set the `isReachStart` prop to true.
     * <ko>시작에 도달해서 더 이상 추가할 그룹(또는 아이템)이 없는 경우 호출해라. 또는 `isReachStart` 옵션을 true로 설정해라.</ko>
     */
    reachStart(): void;
    /**
     * Set to standby to request data.
     * <ko>데이터를 요청하기 위해 대기 상태로 설정한다.</ko>
     */
    wait(): void;
    /**
     * When the data request is complete, it is set to ready state.
     * <ko>데이터 요청이 끝났다면 준비 상태로 설정한다.</ko>
     */
    ready(): void;
}
/**
 * @typedef
 * @property - An InfiniteGrid instance that triggered this event. <ko>이 이벤트를 트리거한 InfiniteGrid의 인스턴스</ko>
 * @property - The items rendered for the first time. <ko>처음 렌더링한 아이템들.</ko>
 * @property - The items updated in size. <ko>사이즈 업데이트한 아이템들.</ko>
 * @property - The direction InfiniteGrid was rendered. <ko>InfiniteGrid가 렌더링된 방향.</ko>
 * @property - Whether rendering was done using the resize event or the useResize option. <ko>resize 이벤트 또는 useResize 옵션을 사용하여 렌더링를 했는지 여부.</ko>
 * @property - The key of the first group that has been rendered. <ko>렌더링이 완료된 첫번째 그룹의 키.</ko>
 * @property - The key of the last group that has been rendered. <ko>렌더링이 완료된 마지막 그룹의 키.</ko>
 * @property - Items that have been rendered. <ko>렌더링이 완료된 아이템들.</ko>
 * @property - Groups that have been rendered. <ko>렌더링이 완료된 그룹들.</ko>
 */
export interface OnRenderComplete {
    currentTarget: InfiniteGrid;
    mounted: InfiniteGridItem[];
    updated: InfiniteGridItem[];
    direction: "start" | "end";
    isResize: boolean;
    startCursor: number;
    endCursor: number;
    items: InfiniteGridItem[];
    groups: InfiniteGridGroup[];
}
/**
 * @typedef
 * @property - An InfiniteGrid instance that triggered this event. <ko>이 이벤트를 트리거한 InfiniteGrid의 인스턴스</ko>
 * @property - The item's element.<ko>아이템의 엘리먼트.</ko>
 * @property - The content element with error.<ko>에러난 발생한 콘텐츠 엘리먼트.</ko>
 * @property - The item with error content.<ko>에러난 콘텐츠를 가지고 있는 아이템</ko>
 * @property - If you have fixed the error and want to recheck it, call update(). If you remove an element, call the syncElements() method.<ko>에러를 해결했고 재검사하고 싶으면 update()를 호출해라. 만약 엘리먼트를 삭제한 경우 syncElements() 메서드를 호출해라.</ko>
 * @property - If you want to remove the item corresponding to the error, call remove(). <ko>에러에 해당하는 아이템을 제거하고 싶으면 remove()를 호출해라.</ko>
 */
export interface OnContentError {
    currentTarget: InfiniteGrid;
    element: HTMLElement;
    target: HTMLElement;
    item: InfiniteGridItem;
    update(): void;
    remove(): void;
}
/**
 * @typedef
 * @property - An InfiniteGrid instance that triggered this event. <ko>이 이벤트를 트리거한 InfiniteGrid의 인스턴스</ko>
 * @property - The scroll direction. <ko>스크롤 방향.</ko>
 * @property - The scroll position. <ko>스크롤 포지션.</ko>
 * @property - The scroll position relative to container. <ko>컨테이너 기준의 스크롤 포지션.</ko>
 */
export interface OnChangeScroll {
    currentTarget: InfiniteGrid;
    direction: "start" | "end";
    scrollPos: number;
    relativeScrollPos: number;
}
export interface InfiniteGridEvents {
    changeScroll: OnChangeScroll;
    requestAppend: OnRequestAppend;
    requestPrepend: OnRequestPrepend;
    renderComplete: OnRenderComplete;
    contentError: OnContentError;
}
export interface OnPickedRenderComplete {
    mounted: GridItem[];
    updated: GridItem[];
    isResize: boolean;
    direction: "start" | "end";
}
export interface OnRequestInsert {
    key: string | number | undefined;
    nextKey: string | number | undefined;
    isVirtual: boolean;
}
export interface RenderingOptions {
    grid: InfiniteGrid<any> | null | undefined;
    status: InfiniteGridStatus | null | undefined;
    useFirstRender: boolean | null | undefined;
    usePlaceholder: boolean | null | undefined;
    useLoading: boolean | null | undefined;
    horizontal: boolean | null | undefined;
}
export declare type InfiniteGridInsertedItems = string | Array<string | InfiniteGridItemInfo | HTMLElement>;
export declare type InfiniteGridMethods<Component> = Methods<Component, InfiniteGrid, typeof INFINITEGRID_METHODS>;
export declare type InfiniteGridFunction = (new (container: HTMLElement, options: Partial<GridOptions>) => InfiniteGrid) & {
    propertyTypes: any;
    defaultOptions: any;
};
