import { BBox } from 'geojson';
import { default as default_2 } from 'eventemitter3';
import { default as default_3 } from '@linkurious/ogma';
import { Feature } from 'geojson';
import { FeatureCollection } from 'geojson';
import { Geometry } from 'geojson';
import { GeometryObject } from 'geojson';
import { LineString } from 'geojson';
import { Options } from '@linkurious/ogma';
import { Overlay } from '@linkurious/ogma';
import { Point as Point_2 } from '@linkurious/ogma';
import { Polygon } from 'geojson';
import { Position } from 'geojson';
import { SVGLayer } from '@linkurious/ogma';

export declare type Annotation = Arrow | Text_2;

export declare interface AnnotationCollection extends FeatureCollection {
    features: (Arrow | Text_2)[];
}

export declare interface AnnotationFeature<G extends GeometryObject = GeometryObject, P = AnnotationProps> extends Feature<G, P> {
    id: string | number;
}

export declare type AnnotationOptions = {
    handleSize: number;
    placeholder: string;
};

export declare interface AnnotationProps {
    type: AnnotationType;
    style?: unknown;
}

declare type AnnotationType = "arrow" | "text";

export declare type Arrow = AnnotationFeature<LineString, ArrowProperties>;

export declare interface ArrowProperties extends AnnotationProps {
    type: "arrow";
    style?: ArrowStyles;
    link?: Partial<Record<Side, ExportedLink>>;
}

/**
 * @class Arrows
 * Draw and edit arrows
 */
export declare class Arrows extends Editor<Arrow> {
    private draggedHandle;
    private start;
    private end;
    private arrow;
    private startX;
    private startY;
    private minArrowHeight;
    private maxArrowHeight;
    private handles;
    constructor(ogma: default_3, options?: Pick<Partial<ControllerOptions>, "arrowHandleSize" | "maxArrowHeight" | "minArrowHeight">);
    private onHandleMouseDown;
    /**
     * Start drawing a new arrow, it will also be added as a new annotation
     * @param x
     * @param y
     * @param arrow
     */
    startDrawing(x: number, y: number, arrow?: Arrow): void;
    cancelDrawing(): void;
    private startDragging;
    private onMouseUp;
    private onMouseMove;
    detect(point: Point_2, margin?: number): Arrow | undefined;
    refreshEditor(): void;
    getDefaultOptions(): Arrow;
    draw(svg: SVGSVGElement): void;
    refreshDrawing(): void;
    destroy(): void;
}

export declare interface ArrowStyles extends StrokeOptions {
    tail?: Extremity;
    head?: Extremity;
}

/**
 * Bounding box object, with the following properties:
 * - [0]: min x
 * - [1]: min y
 * - [2]: max x
 * - [3]: max y
 */
export declare type Bounds = [number, number, number, number];

export declare function clientToContainerPosition(evt: {
    clientX: number;
    clientY: number;
}, container?: HTMLElement | null): {
    x: number;
    y: number;
};

export declare function colorToRgba(color: string, alpha: number): string;

export declare class Control extends default_2<FeatureEvents> {
    private arrows;
    private texts;
    private links;
    private layer;
    private annotations;
    private ogma;
    private options;
    private selected;
    private updateTimeout;
    private hoveredNode;
    private dragged;
    private textToMagnet;
    private activeLinks;
    constructor(ogma: default_3, options?: Partial<ControllerOptions>);
    private _render;
    private _onFeatureDrag;
    private _onFeatureDragEnd;
    private _onFeatureDragStart;
    private _onNodesDragStart;
    private _onNodesDrag;
    private _onLayoutEnd;
    private _moveNodes;
    private _snapToText;
    private _findAndSnapToNode;
    private _snapToNode;
    private _onAdded;
    private _onRemoved;
    private _onUnselect;
    private _onSelect;
    private refreshTextLinks;
    /**
     * @returns the currently selected annotation
     */
    getSelected(): Annotation | null;
    private findMagnetPoint;
    /**
     * Set the options for the controller
     * @param options new Options
     * @returns the updated options
     */
    setOptions(options?: Partial<ControllerOptions>): ControllerOptions;
    /**
     * Selects the annotation with the given id
     * @param id the id of the annotation to select
     */
    select(id: Id): this;
    /**
     * Unselects the currently selected annotation
     */
    unselect(): this;
    /**
     * Add an annotation to the controller
     * @param annotation The annotation to add
     */
    add(annotation: Arrow | Text_2 | AnnotationCollection): this;
    /**
     * Remove an annotation or an array of annotations from the controller
     * @param annotation The annotation(s) to remove
     */
    remove(annotation: Arrow | Text_2 | AnnotationCollection): this;
    private loadLink;
    /**
     * Start adding an arrow (add it, and give control to the user)
     * @param x coord of the first point
     * @param y coord of the first point
     * @param arrow The arrow to add
     */
    startArrow(x: number, y: number, arrow?: Arrow): void;
    /**
     * Start adding a text (add it, and give control to the user)
     * @param x coord of the top left point
     * @param y coord of the top left point
     * @param text The text to add
     */
    startText(x: number, y: number, text?: Text_2): void;
    /**
     * Cancel drawing on the current frame
     */
    cancelDrawing(): void;
    /**
     * Triggers the update event on the annotation
     * @param annotation The annotation updated
     */
    onUpdate: (annotation: Annotation) => void;
    private _onUpdate;
    /**
     * Update the style of the annotation with the given id
     * @param id The id of the annotation to update
     * @param style The new style
     */
    updateStyle<A extends Annotation>(id: Id, style: A["properties"]["style"]): this;
    setScale(id: Id, scale: number, ox: number, oy: number): this;
    /**
     * @returns the annotations in the controller
     */
    getAnnotations(): AnnotationCollection;
    /**
     * Retrieve the annotation with the given id
     * @param id the id of the annotation to get
     * @returns The annotation with the given id
     */
    getAnnotation(id: Id): Arrow | Text_2 | undefined;
    /**
     * Destroy the controller and its elements
     */
    destroy(): void;
}

export declare type ControllerOptions = {
    /**
     * The color of the magnet points
     */
    magnetColor: string;
    /**
     * The radius in which arrows are attracted
     */
    magnetRadius: number;
    /**
     * The margin in which the Texts are detected when looking for magnet points
     */
    detectMargin: number;
    /**
     * Display size of the magnet point
     */
    magnetHandleRadius: number;
    /**
     * Placeholder for the text input
     */
    textPlaceholder: string;
    /**
     * Size of the text handle
     */
    textHandleSize: number;
    /**
     * Size of the arrow handle
     */
    arrowHandleSize: number;
    /**
     * Minimum height of the arrow in units
     */
    minArrowHeight: number;
    /**
     * Maximum height of the arrow in units
     */
    maxArrowHeight: number;
};

export declare const createArrow: (x0?: number, y0?: number, x1?: number, y1?: number, styles?: {
    tail?: Extremity | undefined;
    head?: Extremity | undefined;
    strokeType?: "none" | "plain" | "dashed" | undefined;
    strokeColor?: string | undefined;
    strokeWidth?: number | undefined;
}) => Arrow;

export declare function createSVGElement<T extends SVGElement>(tag: string): T;

export declare const createText: (x?: number, y?: number, width?: number, height?: number, content?: string, styles?: Partial<TextStyle>) => Text_2;

export declare const defaultArrowOptions: Arrow;

export declare const defaultArrowStyle: ArrowStyles;

export declare const defaultControllerOptions: AnnotationOptions;

export declare const defaultTextOptions: Text_2;

export declare const defaultTextStyle: TextStyle;

/**
 * @class Annotations
 * Abstract class to display Texts and Arrows, provide add/remove/update and mouse events
 * Modifying annotation is handled by the child classes, it is too specific
 */
declare abstract class Editor<T extends Annotation> extends default_2<Events<T>> {
    protected ogma: default_3;
    protected elements: T[];
    protected layer: SVGLayer;
    protected editor: Overlay;
    protected selectedId: Id;
    protected hoveredId: Id;
    protected ogmaOptions: Options;
    protected shouldDetect: boolean;
    protected isDragging: boolean;
    protected showeditorOnHover: boolean;
    constructor(ogma: default_3, editorHtml: string);
    private _onKeyUp;
    protected _canRemove(): boolean;
    private _onClickMouseMove;
    /**
     * @method add
     * @param options Params for the annotation (merged with default)
     * @returns the added annotation
     */
    add(options: T): T;
    updateStyle(annotation: T, style: Partial<T["properties"]["style"]>): void;
    updateGeometry(annotation: T, geometry: Partial<T["geometry"]>): void;
    scale(annotation: T, scale: number, ox: number, oy: number): void;
    /**
     * @method update
     * Updates an annotation (position, color etc)
     * @param id Id of the annotation to update
     * @param element params of the annotation
     */
    update(id: Id, element: Partial<T>): void;
    updateAnnotation(target: T, element: Partial<T>): void;
    getById(id: Id): T;
    /**
     * @method select
     * @param id id of the element to select
     * Select element, show editor, disable Ogma dragging and fire event
     */
    select(id: Id): void;
    hover(id: Id): void;
    getSelectedFeature(): T | null;
    unselect(): this;
    unhover(): this;
    /**
     * @method remove
     * @param id Id of the annotation to remove
     * Removes annotation with the given id
     */
    remove(id: Id): void;
    /**
     * @method disableDragging
     * Prevents Ogma from dragging elements or moving the view while dragging an annotation
     */
    disableDragging(): void;
    /**
     * @method restoreDragging
     * restore ogma options as they were before we start dragging an annotation
     */
    restoreDragging(): void;
    enableDetection(): void;
    /**
     * @method disableDetection
     * Disables the hover behaviour, used by controller to avoid hovering
     * arrows while dragging texts and vice versa
     */
    disableDetection(): void;
    refreshLayer(): void;
    refreshDrawing(): void;
    getElements(): T[];
    abstract refreshEditor(): void;
    abstract draw(svg: SVGSVGElement): void;
    abstract cancelDrawing(): void;
    abstract getDefaultOptions(): T;
    abstract detect(point: Point_2, margin: number): T | undefined;
    destroy(): void;
}

export declare type Events<T> = {
    [EVT_HOVER]: (evt: T) => void;
    [EVT_UNHOVER]: (evt: T) => void;
    [EVT_SELECT]: (evt: T) => void;
    [EVT_UNSELECT]: (evt: T) => void;
    [EVT_DRAG_START]: (evt: T) => void;
    [EVT_DRAG]: (evt: T, key: "line" | "start" | "end" | "text") => void;
    [EVT_DRAG_END]: (evt: T) => void;
    [EVT_REMOVE]: (evt: T) => void;
    [EVT_ADD]: (evt: T) => void;
    [EVT_UPDATE]: (evt: T) => void;
};

export declare const EVT_ADD = "add";

export declare const EVT_CANCEL_DRAWING = "cancelDrawing";

export declare const EVT_DRAG = "dragging";

export declare const EVT_DRAG_END = "dragend";

export declare const EVT_DRAG_START = "dragstart";

export declare const EVT_HOVER = "hover";

export declare const EVT_LINK = "link";

export declare const EVT_REMOVE = "remove";

export declare const EVT_SELECT = "select";

export declare const EVT_UNHOVER = "unhover";

export declare const EVT_UNSELECT = "unselect";

export declare const EVT_UPDATE = "update";

declare type ExportedLink = {
    id: Id;
    side: "start" | "end";
    type: "node" | "text";
    magnet?: Point;
};

export declare type Extremity = "none" | "arrow" | "arrow-plain" | "dot" | "halo-dot";

export declare type FeatureEvents = {
    /**
     * Event trigerred when selecting an annotation
     * @param evt The annotation selected
     */
    [EVT_SELECT]: (evt: Annotation) => void;
    /**
     * Event trigerred when unselecting an annotation
     * @param evt The annotation unselected
     */
    [EVT_UNSELECT]: (evt: Annotation) => void;
    /**
     * Event trigerred when removing an annotation
     * @param evt The annotation removed
     */
    [EVT_REMOVE]: (evt: Annotation) => void;
    /**
     * Event trigerred when adding an annotation
     * @param evt The annotation added
     */
    [EVT_ADD]: (evt: Annotation) => void;
    [EVT_CANCEL_DRAWING]: () => void;
    /**
     * Event trigerred when updating an annotation
     * @returns The annotation updated
     */
    [EVT_UPDATE]: (evt: Annotation) => void;
    /**
     * Event trigerred when linking an arrow to a text or node
     */
    [EVT_LINK]: (evt: {
        arrow: Arrow;
        link: Link;
    }) => void;
    /**
     * Event trigerred when starting to drag an arrow or a text
     */
    [EVT_DRAG_START]: (evt: Arrow | Text_2) => void;
    /**
     * Event trigerred when dragging an arrow or a text
     */
    [EVT_DRAG]: (evt: Arrow | Text_2, key: "line" | "start" | "end" | "text") => void;
    /**
     * Event trigerred when stopped dragging an arrow or a text
     */
    [EVT_DRAG_END]: (evt: Arrow | Text_2) => void;
};

/**
 * Calculate the bounds of a collection of annotations
 * @param annotations
 */
export declare function getAnnotationsBounds(annotations: AnnotationCollection): Bounds;

export declare function getArrowEnd(a: Arrow): {
    x: number;
    y: number;
};

export declare function getArrowEndPoints(a: Arrow): {
    start: {
        x: number;
        y: number;
    };
    end: {
        x: number;
        y: number;
    };
};

export declare function getArrowSide(a: Arrow, side: "start" | "end"): {
    x: number;
    y: number;
};

export declare function getArrowStart(a: Arrow): {
    x: number;
    y: number;
};

export declare function getAttachmentPointOnNode(start: Point_2, nodeCenter: Point_2, nodeRadius: number): {
    x: number;
    y: number;
};

export declare function getCoordinates(gj: Feature | FeatureCollection | Geometry): Position[];

export declare const getHandleId: (handle: HTMLDivElement) => number;

export declare function getTextBbox(t: Text_2): BBox;

export declare function getTextPosition(t: Text_2): {
    x: number;
    y: number;
};

export declare function getTextSize(t: Text_2): {
    width: number;
    height: number;
};

export declare function hexShortToLong(color: string): string;

export declare function hexToRgba(color: string, alpha: number): string;

export declare type Id = string | number;

export declare const isAnnotationCollection: (a: AnnotationFeature<Geometry, AnnotationProps> | FeatureCollection) => a is AnnotationCollection;

export declare const isArrow: (a: AnnotationFeature<Geometry, AnnotationProps>) => a is Arrow;

export declare const isText: (a: AnnotationFeature<Geometry, AnnotationProps>) => a is Text_2;

export declare type Link = {
    /** arrow attached to the text or node */
    arrow: Id;
    /** id of the text the arrow is attached to */
    id: Id;
    /**  On which end the arrow is tighten to the text */
    side: Side;
    /** id of the text or node  the arrow is attached to */
    target: Id;
    /** Text or node */
    targetType: TargetType;
    /**
     * On which point relative to topleft corner the arrow is tighten, in case of
     * node, it can be deduced from the arrow itself
     */
    connectionPoint: Point;
};

export declare const NONE = -1;

export declare type Point = {
    x: number;
    y: number;
};

export declare function rgbToRgba(color: string, alpha: number): string;

export declare function scaleGeometry(geometry: LineString | Polygon, scale: number, ox: number, oy: number): LineString | Polygon;

export declare function setArrowEnd(a: Arrow, x: number, y: number): void;

export declare function setArrowEndPoint(a: Arrow, side: "start" | "end", x: number, y: number): void;

export declare function setArrowStart(a: Arrow, x: number, y: number): void;

export declare function setTextBbox(t: Text_2, x: number, y: number, width: number, height: number): void;

export declare type Side = "start" | "end";

export declare type Stroke = {
    type: "plain" | "dashed" | "none";
    color: string;
    width: number;
};

export declare type StrokeOptions = {
    strokeType?: "plain" | "dashed" | "none";
    strokeColor?: string;
    strokeWidth?: number;
};

export declare type StrokeStyle = Stroke;

export declare type TargetType = "text" | "node";

declare type Text_2 = AnnotationFeature<Polygon, TextProperties>;
export { Text_2 as Text }

export declare interface TextProperties extends AnnotationProps {
    type: "text";
    /**text to display*/
    content: string;
    style?: TextStyle;
}

/**
 * @class Texts
 * Draw, update, edit texts
 */
export declare class Texts extends Editor<Text_2> {
    private textArea;
    private handleSize;
    private rect;
    private annotation;
    private startX;
    private startY;
    private handles;
    private draggedHandle;
    private isFocused;
    private placeholder;
    constructor(ogma: default_3, options?: Pick<Partial<ControllerOptions>, "textHandleSize" | "textPlaceholder">);
    private _onFocus;
    private _onBlur;
    protected _canRemove(): boolean;
    startDrawing: (x: number, y: number, text?: Text_2) => void;
    cancelDrawing: () => void;
    private startDragging;
    private onHandleMouseDown;
    private onMouseMove;
    private _onMouseMove;
    private onMouseUp;
    private _onMousedown;
    private onViewChanged;
    private _onInput;
    detect({ x, y }: Point_2, margin?: number): Text_2 | undefined;
    draw(svg: SVGSVGElement): void;
    refreshDrawing(): void;
    getDefaultOptions(): Text_2;
    refreshEditor(): void;
    select(id: Id): void;
    destroy(): void;
}

export declare interface TextStyle extends StrokeOptions {
    /** Helvetica, sans-serif...  */
    font?: string;
    /** Font size, in pixels */
    fontSize?: number | string;
    /** text color: #f00, yellow...*/
    color?: string;
    /** background color: empty for transparent #f00, yellow...*/
    background?: string;
    /** padding around the text */
    padding?: number;
    /** Text box border radius */
    borderRadius?: number;
}

export declare function updateTextBbox(t: Text_2): void;

export declare type Vector = Point;

export { }
