export interface EventHandler<T> {
    (args: T): void;
}

export class Modal extends ModalPropsAndEvents {
    constructor(options?: ModalConfig)
    close(result?: any): void;
    closeSerialized(): void;
    showHtml(html: string | HTMLElement): void;
    showUrl(url: string): void;
    stretch(): void;
}

export class ModalPropsAndEvents {
    autoFocus?: boolean;
    autoStretch?: boolean;
    autoStretchFirstLoadOnly?: boolean;
    container?: HTMLElement;
    disposeOnClose?: boolean;
    dragDrop?: boolean;
    focus?: string | { id: string, value: string | number};
    height?: number;
    left?: number;
    loadingHtml?: string;
    maxHeight?: number;
    scrollWithPage?: boolean;
    theme?: string;
    top?: number;
    useIframe?: boolean;
    width?: number;
    zIndex?: number;

    onClose?: EventHandler<ModalCloseArgs>;
    onClosed?: EventHandler<ModalClosedArgs>;
    onShow?: EventHandler<ModalShowArgs>;
    onChange?: EventHandler<ModalChangeArgs>;
}

export namespace Modal {
    function close(): void;
    function opener(): void;
    function prompt(message: string, defaultValue?: string, options?: ModalPromptConfig): Promise<ModalClosedArgs>;
    function alert(message: string, options?: ModalAlertConfig): Promise<ModalClosedArgs>;
    function confirm(message: string, options?: ModalConfirmConfig): Promise<ModalClosedArgs>;
    function form(form?: ModalFormItem[], data?: any, options?: ModalFormConfig): Promise<ModalClosedArgs>;

    namespace Experimental {
        class Form {
            form: ModalFormItem[];
            data: any;
            onKey: EventHandler<any>;
            onChange: EventHandler<any>;
            theme: string;
            plugins: any[];
            locale: string;
            zIndex: number;
            create(): Element;
            validate(): void;
            serialize(): any;
        }
    }
}

export class ModalConfig extends ModalPropsAndEvents {
}

export class ModalAlertConfig extends ModalConfig {
    okText?: string;
}

export class ModalConfirmConfig extends ModalConfig {
    okText?: string;
    cancelText?: string;
}

export class ModalPromptConfig extends ModalConfig {
    okText?: string;
    cancelText?: string;
}

export class ModalFormConfig extends ModalConfig {
    okText?: string;
    okDisabled?: boolean;
    cancelText?: string;
    locale?: string;
    plugins?: any;
}

export interface ModalCloseArgs {
    canceled: boolean;
    result: any;
    backgroundClick: boolean;

    preventDefault(): void;
}

export interface ModalClosedArgs {
    canceled: boolean;
    result: any;
    backgroundClick: boolean;
}

export interface ModalShowArgs {
    root: Node;
    modal: Modal;
}

export interface ModalChangeArgs {
    result: any;
}

export interface ModalFormItem {
    id?: string;
    name?: string;
    type?: "text" | "date" | "searchable" | "select" | "radio" | "checkbox" | "table" | "title" | "image" | "html" | "textarea" | "scrollable" | "time" | "datetime" | string;
    image?: string;
    dateFormat?: string;
    disabled?: boolean;
    disableParents?: boolean;
    cssClass?: string;
    options?: ModalFormOption[];
    children?: ModalFormItem[];
    columns?: ModalFormTableColumns[];
    onValidate?: EventHandler<ModalFormItemValidationArgs>;
    onNewRow?: EventHandler<ModalFormTableItemNewRowArgs>;
    height?: number;
    text?: string;
    html?: string;
    timeFormat?: string;
    timeInterval?: 1 | 5 | 10 | 15 | 20 | 30 | 60;
}

export interface ModalFormOption {
    id: string | number | boolean;
    name?: string;
    children?: ModalFormItem[];
}

export interface ModalFormTableColumns {
    id: string;
    name: string;
    type?: "text" | "number" | "select";
    options?: ModalFormOption[];
}

export interface ModalFormItemValidationArgs {
    value: any;
    result: any;
    valid: boolean;
    message: string;
}

export interface ModalFormTableItemNewRowArgs {
    value: any;
    result: any;
}
