import { Options } from 'html2canvas';

declare type NodeCoordinate = {
    x: number;
    y: number;
    order: number;
};

declare type SystemCursor = 'auto' | 'default' | 'none' | 'context-menu' | 'help' | 'pointer' | 'progress' | 'wait' | 'cell' | 'crosshair' | 'text' | 'vertical-text' | 'alias' | 'copy' | 'move' | 'no-drop' | 'not-allowed' | 'all-scroll' | 'col-resize' | 'row-resize' | 'n-resize' | 'e-resize' | 's-resize' | 'w-resize' | 'ns-resize' | 'ew-resize' | 'ne-resize' | 'nw-resize' | 'se-resize' | 'sw-resize' | 'nesw-resize' | 'nwse-resize';
declare type CustomCursor = string;
declare type Cursor = SystemCursor | Omit<string, CustomCursor>;

declare type GraphDrawingStyles = {
    node: Partial<{
        shape: 'circle' | 'pathX';
        color: string;
        hoverColor: string;
        hoverSizeMultiplier: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
        width: number;
        transition: string;
        cursor: Cursor;
    }>;
    line: Partial<{
        color: string;
        width: number;
    }>;
};
declare type GraphDrawingConfig = {
    canDrawLines?: boolean;
    canRemoveNodes?: boolean;
    styles?: Partial<GraphDrawingStyles>;
};

/**
 * Define primitive behavior for SVG graph drawing
 */
declare abstract class GraphDrawing {
    protected containerElement: HTMLDivElement | null;
    private config;
    protected set wrapperElement(element: HTMLDivElement);
    protected get nodes(): NodeListOf<SVGElement | SVGCircleElement> | undefined;
    protected set node(args: {
        x: number;
        y: number;
    } & Required<GraphDrawingStyles['node']>);
    protected get lines(): NodeListOf<SVGLineElement> | undefined;
    protected set line(args: {
        x1: string;
        y1: string;
        x2: string;
        y2: string;
        color: string;
        width: number;
    });
    constructor(config?: GraphDrawingConfig | undefined);
    /**
     * Return current graph config
     */
    getCurrentConfig(): GraphDrawingConfig;
    /**
     * Return parent HTML element
     */
    getContainerElement(): HTMLDivElement | null;
    /**
     * Returns list of nodes
     */
    getNodes(): NodeListOf<SVGElement | SVGCircleElement> | undefined;
    /**
     * Returns list of nodes coordinates
     */
    getCoordinates(): NodeCoordinate[];
    /**
     * Load node coordinates and redraw lines
     */
    loadCoordinates(coordinates: NodeCoordinate[]): void;
    /**
     * Export frame as the specified mime type
     * @param mimeType file media identifier
     * @param options export options
     * @returns file encoded in base64
     */
    exportAs(mimeType: 'image/jpeg' | 'image/png', options?: Partial<Options>): Promise<string>;
    /**
     * Allow users to draw lines and connect nodes
     */
    enableDrawingLines(): void;
    /**
     * Prevent users from drawing lines and connecting nodes
     */
    disableDrawingLines(): void;
    /**
     * Allow users to remove nodes
     */
    enableNodesRemoval(): void;
    /**
     * Prevent users from removing nodes
     */
    disableNodesRemoval(): void;
    /**
     * Compile drawing configuration on demand and set up events
     * @param configUpdates config schema
     */
    compile(configUpdates?: GraphDrawingConfig): void;
    /**
     * Recursively merge configuration object with configuration updates
     * @param config initial configuration object
     * @param updates any config updates
     */
    mergeConfig(config: GraphDrawingConfig, updates: Partial<GraphDrawingConfig>): GraphDrawingConfig;
    /**
     * Create frame for specified  source
     * @param config tree structure config
     */
    abstract mountScopedFrame(config: object): GraphDrawing;
    /**
     * Add implementation for drawing events
     */
    abstract startProcess(): GraphDrawing;
    /**
     * Traverse nodes and connect them
     */
    abstract redraw(): void;
    private getCircleContext;
    private getPathXContext;
}

/**
 * Logic implementation for lines drawing on SVG frames
 */
declare class LineGraphDrawing extends GraphDrawing {
    isHttpImageUrl: boolean;
    constructor(config?: GraphDrawingConfig);
    mountScopedFrame(config: {
        image: {
            src: string;
            alt?: string;
            objectFit?: 'fill' | 'contain' | 'cover' | 'none' | 'scale-down';
        };
        container?: {
            boundaries?: Array<Partial<{
                width: string;
                height: string;
                inset: string;
                backgroundColor?: string;
                opacity?: number;
                cursor?: Cursor;
            }>>;
            styles?: Partial<{
                width: string;
                heigth: string;
            }>;
        };
        frame?: {
            styles?: {
                backgroundColor?: string;
                opacity?: number;
                cursor?: Cursor;
            };
        };
    }): LineGraphDrawing;
    startProcess(): LineGraphDrawing;
    redraw(): void;
}

export { LineGraphDrawing };
