import React, { FC } from 'react';

declare class SVGEl {
    node: SVGElement;
    private events;
    constructor(node: SVGElement, events?: {
        event: string;
        cb: EventListener;
    }[]);
    append: (el: SVGEl) => void;
    fill(color: string): this;
    move(x: number, y: number): this;
    addClass(name: string): this;
    removeClass(name: string): this;
    stroke(obj: {
        color?: string;
        width?: number;
        opacity?: number;
        dasharray?: string;
    }): this;
    getAttr: (name: string) => string | null;
    attr(name: string, value: string): this;
    register(event: string, cb: EventListener): void;
    mouseup(cb: (ev: MouseEvent) => any): this;
    mousedown(cb: (ev: MouseEvent) => any): this;
    mousemove(cb: (ev: MouseEvent) => any): this;
    mouseover(cb: (ev: MouseEvent) => any): this;
    mouseout(cb: (ev: MouseEvent) => any): this;
    click(cb: (ev: MouseEvent) => any): this;
    dblclick(cb: (ev: MouseEvent) => any): this;
    on(event: string, cb: (ev: any) => any): this;
    off(event: string): this;
    opacity(o: number): this;
    remove: () => void;
    increment(d: [x: number, y: number]): void;
    after: (el: SVGEl) => void;
    before: (el: SVGEl) => void;
}
declare class CircleEl extends SVGEl {
    node: SVGCircleElement;
    constructor(node: SVGCircleElement);
    increment: typeof roundIncrement;
    x: typeof RoundElX;
    y: typeof RoundElY;
    radius(r: number): this;
}
declare class EllipseEl extends SVGEl {
    node: SVGEllipseElement;
    constructor(node: SVGEllipseElement);
    increment: typeof roundIncrement;
    x: typeof RoundElX;
    y: typeof RoundElY;
    radius(rx: number, ry: number): this;
}
declare class RectEl extends SVGEl {
    node: SVGRectElement;
    constructor(node: SVGRectElement);
    radius(r: number): this;
    move(x: number, y: number): this;
}
declare class PolylineEl extends SVGEl {
    node: SVGPolylineElement;
    constructor(node: SVGPolylineElement);
    array(): number[][];
    plot(points: [number, number][]): void;
    increment(d: [x: number, y: number]): void;
}
declare class TextEl extends SVGEl {
    node: SVGTextElement;
    constructor(node: SVGTextElement);
    font(size: number, weight: string, fill?: string, anchor?: string): this;
    move(x: number, y: number): this;
    bbox: () => DOMRect;
}
declare class PathEl extends SVGEl {
    node: SVGPathElement;
    constructor(node: SVGPathElement);
    plot(d: string): this;
}
declare class ImageEl extends SVGEl {
    node: SVGImageElement;
    constructor(node: SVGImageElement);
    size(w: string, h: string): this;
    bbox: () => DOMRect;
}
declare class SVGSVGEl extends SVGEl {
    node: SVGSVGElement;
    constructor(node: SVGSVGElement);
    circle(r: number): CircleEl;
    ellipse(rx: number, ry: number): EllipseEl;
    rect(w: number, h: number): RectEl;
    polyline(points: [number, number][]): PolylineEl;
    plain(text: string): TextEl;
    path(d: string): PathEl;
    image(url: string, onload: (target: ImageEl) => any): ImageEl;
    size(w: number, h: number): void;
}
declare function RoundElX(this: SVGEl, x?: number): any;
declare function RoundElY(this: SVGEl, y?: number): any;
declare function roundIncrement(this: CircleEl | EllipseEl, d: [x: number, y: number]): void;

type Point = {
    X: number;
    Y: number;
};
type ArrayXY = [number, number];
type Shortcut = {
    del?: boolean;
    bksp?: boolean;
};
declare abstract class Shape {
    categories: string[];
    phi: number;
    color?: string | undefined;
    id: number;
    getCenterWithOffset: () => Point;
    abstract type: string;
    abstract labelPosition(vertical: 'top' | 'middle' | 'bottom'): ArrayXY;
    abstract getCenter(): ArrayXY;
    abstract zoom(factor: number): void;
    abstract output(ratio: number): Shape;
    abstract centerChanged(newCenter: ArrayXY): void;
    constructor(categories?: string[], phi?: number, color?: string | undefined);
    getOutput(ratio: number, svg: SVGSVGEl): Shape;
    rotatePosition(): ArrayXY;
}
declare class Dot extends Shape {
    position: ArrayXY;
    categories: string[];
    color?: string | undefined;
    type: string;
    constructor(position?: ArrayXY, categories?: string[], color?: string | undefined);
    labelPosition(vertical: 'top' | 'middle' | 'bottom'): ArrayXY;
    getCenter(): ArrayXY;
    zoom(factor: number): void;
    output(ratio: number): Dot;
    centerChanged(newPos: ArrayXY): void;
}
declare abstract class AngledShape extends Shape {
    points: ArrayXY[];
    categories: string[];
    color?: string | undefined;
    constructor(points?: ArrayXY[], categories?: string[], color?: string | undefined);
    labelPosition(vertical: 'top' | 'middle' | 'bottom'): ArrayXY;
    outPoints(ratio: number): ArrayXY[];
    getCenter(): ArrayXY;
    centerChanged(newCenter: ArrayXY): void;
    zoom(factor: number): void;
}
declare class Rectangle extends AngledShape {
    type: string;
    output(ratio: number): Rectangle;
}
declare class Polygon extends AngledShape {
    type: string;
    output(ratio: number): Polygon;
}
declare abstract class RoundShape extends Shape {
    centre: ArrayXY;
    categories: string[];
    phi: number;
    color?: string | undefined;
    constructor(centre?: ArrayXY, categories?: string[], phi?: number, color?: string | undefined);
    abstract get width(): number;
    abstract set width(w: number);
    abstract get height(): number;
    abstract set height(h: number);
    getCenter(): ArrayXY;
    centerChanged(newCenter: ArrayXY): void;
}
declare class Circle extends RoundShape {
    centre: ArrayXY;
    radius: number;
    categories: string[];
    color?: string | undefined;
    type: string;
    constructor(centre?: ArrayXY, radius?: number, categories?: string[], color?: string | undefined);
    get width(): number;
    set width(w: number);
    get height(): number;
    set height(h: number);
    labelPosition(vertical: 'top' | 'middle' | 'bottom'): ArrayXY;
    zoom(factor: number): void;
    output: (ratio: number) => Shape;
}
declare class Ellipse extends RoundShape {
    centre: ArrayXY;
    radiusX: number;
    radiusY: number;
    categories: string[];
    phi: number;
    color?: string | undefined;
    type: string;
    constructor(centre?: ArrayXY, radiusX?: number, radiusY?: number, categories?: string[], phi?: number, color?: string | undefined);
    get width(): number;
    set width(w: number);
    get height(): number;
    set height(h: number);
    labelPosition(vertical: 'top' | 'middle' | 'bottom'): ArrayXY;
    zoom(factor: number): void;
    output: (ratio: number) => Shape;
}

declare const useImageAnnotator: () => {
    setHandles: React.Dispatch<React.SetStateAction<AnnotatorHandles | undefined>>;
    annotator: AnnotatorHandles | undefined;
};
type AnnotatorHandles = {
    drawRectangle(): void;
    drawPolygon(): void;
    drawCircle(): void;
    drawEllipse(): void;
    drawDot(): void;
    stop: () => void;
    stopEdit: () => void;
    edit: (id: number) => void;
    delete: (id: number) => void;
    updateCategories: (id: number, categories: string[], color?: string) => void;
    zoom: (factor: number, relative?: boolean) => void;
    getShapes: () => Shape[];
    container: HTMLDivElement;
};

declare const ImageAnnotator: FC<ImageAnnotatorProps>;

interface ImageAnnotatorProps {
    onReady?: (annotator: AnnotatorHandles) => any;
    onAdded?: (shape: Shape) => any;
    onEdited?: (shape: Shape) => any;
    onSelected?: (shape: Shape) => any;
    onContextMenu?: (shape: Shape) => any;
    imageUrl?: string;
    shapes?: Shape[] | any[];
    naturalSize?: boolean;
    width?: number;
    height?: number;
    discRadius?: number;
    hideBorder?: boolean;
    shortcut?: Shortcut;
    categoryOpt?: {
        vertical: 'top' | 'middle' | 'bottom';
    } | undefined;
    setHandles: (handles: AnnotatorHandles) => void;
}

export { Circle, Dot, Ellipse, ImageAnnotator, type Point, Polygon, Rectangle, Shape, useImageAnnotator };
