import { GridColumnDefinition } from "./column"
/**
 * 单元格点击回调函数
 * 
 * @param {number} index - 点击的行索引
 * @param {number} colIndex - 点击的列索引
 * @returns {boolean} 返回 `false` 则取消事件冒泡
 */
declare function cellClickedCallback(index: number, colIndex: number): boolean;

/** 列数据接口 */
interface GridItem {
    /** 值 */
    Value: any;
    /** 显示值 */
    DisplayValue: string;
}

/** 列数据行包装接口 */
interface GridItemWrapper {
    /** 真实数据对象 */
    values: { [key: string]: GridItem | any };
    /** 下拉数据源缓存对象 */
    source: { [key: string]: Array<GridSourceItem> };
}

/** 下拉框列数据源接口 */
interface GridSourceItem {
    /** 值 */
    value: string;
    /** 显示文本 */
    text: string;
}

/** Grid 语言资源接口 */
interface GridLanguages {
    /**
     * “所有”文本，默认值 `( All )` */
    all: string;
    /** “确定”文本，默认值 `OK` */
    ok: string;
    /** “重置”文本，默认值 `Reset` */
    reset: string;
    cancel: string;
    /** “空”文本，默认值 `( Null )` */
    null: string;
    addLevel: string;
    deleteLevel: string;
    copyLevel: string;
    asc: string;
    desc: string;
    column: string;
    order: string;
    sort: string;
    requirePrompt: string;
    duplicatePrompt: string;
}

/** Grid 列排序定义接口 */
interface GridColumnSortDefinition {
    /** 排序列的关键字 */
    column: string;
    /** 升序或降序 */
    order: "asc" | "desc";
}

/** 列排序枚举 */
declare enum GridColumnDirection {
    /** 倒序 */
    Descending = -1,
    /** 升序 */
    Ascending = 1
}

/** 列事件枚举 */
declare enum GridColumnEvent {
    /** 重排事件 */
    Reorder = "reorder",
    /** 宽调整事件 */
    Resize = "resize",
    /** 排序事件 */
    Sort = "sort"
}

/** Grid 控件基础类 */
export class Grid {
    /** 列类型枚举 */
    static ColumnTypes: {
        /** 通用列（只读） */
        Common: 0,
        /** 单行文本列 */
        Input: 1,
        /** 下拉选择列 */
        Dropdown: 2,
        /** 复选框列 */
        Checkbox: 3,
        /** 图标列 */
        Icon: 4,
        /** 多行文本列 */
        Text: 5,
        /** 日期选择列 */
        Date: 6,
        /**
         * 判断列是否为复选框列
         * @param type 列类型
         */
        isCheckbox(type: number): boolean;
    };

    /** 列定义的数组 */
    columns: Array<GridColumnDefinition>;
    /** 多语言资源对象 */
    langs?: GridLanguages;
    /** 行数大于等于该值则启用虚模式，默认值 `100` */
    virtualCount?: number;
    /** 表格行高，默认值 `36` */
    rowHeight?: number;
    /** 文本行高，默认值 `24` */
    lineHeight?: number;
    /** 列表底部留出额外行的空白，默认值 `0` */
    extraRows?: number;
    /** 过滤条件列表的行高，默认值 `30` */
    filterRowHeight?: number;
    /** 列表高度值，为 0 时列表始终显示全部内容（自增高），为非数字或者小于 0 则根据容器高度来确定虚模式的渲染行数，默认值 `null` */
    height?: number;
    /** 是否允许多选，默认值 `false` */
    multiSelect?: boolean;
    /** 为 false 时只有点击在单元格内才会选中行，默认值 `true` */
    fullrowClick?: boolean;
    /** 单元格 tooltip 是否禁用，默认值 `false` */
    tooltipDisabled?: boolean;
    /** 列头是否显示，默认值 `true` */
    headerVisible?: boolean;
    /** 监听事件的窗口载体，默认值 `window` */
    window?: Window
    /** 排序列的索引，默认值 `-1` */
    sortIndex?: number;
    /** 排序方式，正数升序，负数倒序，默认值 `1` */
    sortDirection?: GridColumnDirection;
    /** 排序列 */
    sortArray?: Array<GridColumnSortDefinition>;

    /**
     * Grid 控件构造函数
     * @param container Grid 控件所在的父容器，可以是 string 表示选择器，也可以是 HTMLElement 对象<br/><br/>
     * <i>构造时可以不进行赋值，但是调用 init 函数时则必须进行赋值</i>
     * @param getText （可选参数）获取多语言文本的函数代理
     */
    constructor(container: string | HTMLElement, getText?: (id: string, def?: string) => string);

    /**
     * 即将选中行时触发，返回 false、null、undefined、0 等则取消选中动作
     * @param index 即将选中的行索引
     * @param colIndex 即将选中的列索引
     * @eventProperty
     */
    willSelect?: (index: number, colIndex: number) => boolean;
    /**
     * 单元格单击时触发，colIndex 为 -1 则表示点击的是行的空白处，返回 false 则取消事件冒泡
     * @eventProperty
     */
    cellClicked?: typeof cellClickedCallback;

    /**
     * 选中行发生变化时触发的事件
     * @param index 选中的行索引
     * @eventProperty
     */
    onSelectedRowChanged?: (index?: number) => void;
    /**
     * 单元格双击时触发的事件，colIndex 为 -1 则表示点击的是行的空白处
     * @param index 双击的行索引
     * @param colIndex 双击的列索引
     * @eventProperty
     */
    onCellDblClicked?: (index: number, colIndex: number) => void;
    /**
     * 行双击时触发的事件
     * @param index 双击的行索引
     * @eventProperty
     */
    onRowDblClicked?: (index: number) => void;
    /**
     * 列发生变化时触发的事件
     * @param type 事件类型<br/><br/>
     * "reorder" 为发生列重排事件，此时 value 为目标列索引<br/>
     * "resize" 为发生列宽调整事件，此时 value 为列宽度值<br/>
     * "sort" 为发生列排序事件，此时 value 为 1（升序）或 -1（倒序）
     * @param colIndex 发生变化事件的列索引
     * @param value 变化的值
     * @eventProperty
     */
    onColumnChanged?: (type: GridColumnEvent, colIndex: number, value: number | GridColumnDirection) => void;
    /**
     * 列滚动时触发的事件
     * @param e 滚动事件对象
     * @eventProperty
     */
    onBodyScrolled?: (e: Event) => void;
    /**
     * 多列排序后触发的事件
     * @param array 排序列定义数组
     * @eventProperty
     */
    onSorted?: (array?: Array<GridColumnSortDefinition>) => void;

    /** 返回所有数据的数据（未过滤） */
    get allSource(): Array<GridItem>;
    /** 获取数据数组（已过滤） */
    get source(): Array<GridItem>;
    /** 设置数据，并刷新列表 */
    set source(list: Array<GridItem>);
    /** 获取列表是否为只读，默认值 `false` */
    get readonly(): boolean;
    /** 设置列表是否为只读 */
    set readonly(flag: boolean);
    /** 获取当前选中的行索引的数组 */
    get selectedIndexes(): Array<number>;
    /** 设置当前选中的行索引的数组，并刷新列表 */
    set selectedIndexes(indexes: Array<number>);
    /** 获取 Grid 当前是否处于加载状态 */
    get loading(): boolean;
    /** 使 Grid 进入加载状态 */
    set loading(flag: boolean);
    /** 获取 Grid 当前滚动的偏移量 */
    get scrollTop(): number;
    /** 设置 Grid 滚动偏移量 */
    set scrollTop(top: number);

    /** 获取 Grid 的页面元素 */
    get element(): HTMLElement;
    /** 获取当前 Grid 是否已发生改变 */
    get changed(): boolean;
    /** 获取当前是否为虚模式状态 */
    get virtual(): boolean;
    /** 获取当前排序的列关键字，为 null 则当前无排序列 */
    get sortKey(): string | undefined;
    /** 获取当前选中行的索引，为 -1 则当前没有选中行 */
    get selectedIndex(): number | -1;

    /**
     * 初始化Grid控件
     * @param container 父容器元素，若未传值则采用构造方法中传入的父容器元素
     */
    init(container?: HTMLElement): void;
    /**
     * 设置数据列表，该方法为 set source 属性的语法糖
     * @param source 待设置的数据列表
     */
    setData(source: Array<GridItem>): void;
    /**
     * 设置单行数据
     * @param index 行索引
     * @param item 待设置的行数据值
     */
    setItem(index: number, item: GridItem): void;
    /**
     * 添加行数据
     * @param item 待添加的行数据值
     * @param index 待添加的行索引
     * @returns 返回已添加的行数据
     */
    addItem(item: GridItem, index?: number): GridItem;
    /**
     * 批量添加行数据
     * @param array 待添加的行数据数组
     * @param index 待添加的行索引
     * @returns 返回已添加的行数据数组
     */
    addItems(array: Array<GridItem>, index?: number): Array<GridItem>
    /**
     * 删除行数据
     * @param index 待删除的行索引
     * @returns 返回已删除的行数据
     */
    removeItem(index: number): GridItem;
    /**
     * 批量删除行数据
     * @param indexes 待删除的行索引数组，未传值时删除所有行
     * @returns 返回已删除的行数据数组
     */
    removeItems(indexes?: Array<number>): Array<GridItem>;
    /**
     * 滚动到指定行的位置
     * @param index 待滚动至的行索引
     */
    scrollToIndex(index: number): void;
    /**
     * 调整 Grid 元素的大小，一般需要在宽度变化时（如页面大小发生变化时）调用
     * @param force 是否强制 {@linkcode reload}，默认只有待渲染的行数发生变化时才会调用
     * @param keep 是否保持当前滚动位置
     */
    resize(force?: boolean, keep?: boolean): void;
    /**
     * 重新计算需要渲染的行，并载入元素，一般需要在高度变化时调用
     * @param keep 是否保持当前滚动位置
     */
    reload(keep?: boolean): void;
    /**
     * 重新填充Grid单元格数据
     */
    refresh(): void;
    /**
     * 把所有行重置为未修改的状态
     */
    resetChange(): void;
    /**
     * 根据当前排序字段进行列排序
     * @param reload 为 true 则在列排序后调用 {@linkcode Grid.reload} 方法
     */
    sortColumn(reload?: boolean): void;
    /**
     * 根据当前排序列数组进行多列排序
     * @param reload 为 true 则在多列排序后调用 {@linkcode Grid.reload} 方法
     */
    sort(reload?: boolean): void;
    /**
     * 清除列头复选框的选中状态
     */
    clearHeaderCheckbox(): void;
    /**
     * 显示多列排序设置面板
     */
    showSortPanel(): void;
}