import SerializableCommand from '../commands/SerializableCommand';
import EditorImage from '../image/EditorImage';
import { LineSegment2, Mat33, Path, Rect2 } from '@js-draw/math';
import AbstractRenderer from '../rendering/renderers/AbstractRenderer';
import { ImageComponentLocalization } from './localization';
import Viewport from '../Viewport';
import { Point2 } from '@js-draw/math';
export type LoadSaveData = string[] | Record<symbol, string | number>;
export type LoadSaveDataTable = Record<string, Array<LoadSaveData>>;
export type DeserializeCallback = (data: string) => AbstractComponent;
export declare enum ComponentSizingMode {
    /** The default. The compnent gets its size from its bounding box. */
    BoundingBox = 0,
    /** Causes the component to fill the entire visible region of the screen */
    FillScreen = 1,
    /**
     * Displays the component anywhere (arbitrary location) on the
     * canvas. (Ignoring the bounding box).
     *
     * These components may be ignored unless a full render is done.
     *
     * Intended for compnents that need to be rendered on a full export,
     * but won't be visible to the user.
     *
     * For example, a metadata component.
     */
    Anywhere = 2
}
/**
 * A base class for everything that can be added to an {@link EditorImage}.
 *
 * In addition to the `abstract` methods, there are a few methods that should be
 * overridden when creating a selectable/erasable subclass:
 * - {@link keyPoints}: Overriding this may improve how the component interacts with the selection tool.
 * - {@link withRegionErased}: Override/implement this to allow the component to be partially erased
 *    by the partial stroke eraser.
 */
export default abstract class AbstractComponent {
    private readonly componentKind;
    protected lastChangedTime: number;
    /**
     * The bounding box of this component.
     * {@link getBBox}, by default, returns `contentBBox`.
     * This must be set by components.
     *
     * If this changes, {@link EditorImage.queueRerenderOf} should be called for
     * this object (provided that this object has been added to the editor.)
     *
     * **Note**: This value is ignored if {@link getSizingMode} returns `FillScreen`
     * or `FillImage`.
     */
    protected abstract contentBBox: Rect2;
    private zIndex;
    private id;
    private static zIndexCounter;
    protected constructor(componentKind: string, initialZIndex?: number);
    getId(): string;
    private static deserializationCallbacks;
    static registerComponent(componentKind: string, deserialize: DeserializeCallback | null): void;
    private loadSaveData;
    /**
     * Attach data that can be used while exporting the component (e.g. to SVG).
     *
     * This is intended for use by an {@link ImageLoader}.
     */
    attachLoadSaveData(key: string, data: LoadSaveData): void;
    /** See {@link attachLoadSaveData} */
    getLoadSaveData(): LoadSaveDataTable;
    getZIndex(): number;
    /**
     * @returns the bounding box of this. This can be a slight overestimate if doing so
     * 			significantly improves performance.
     */
    getBBox(): Rect2;
    /**
     * @returns the bounding box of this. Unlike `getBBox`, this should **not** be a rough estimate.
     */
    getExactBBox(): Rect2;
    /**
     * Returns information about how this component should be displayed
     * (e.g. fill the screen or get its size from {@link getBBox}).
     *
     * {@link EditorImage.queueRerenderOf} must be called to apply changes to
     * the output of this method if this component has already been added to an
     * {@link EditorImage}.
     */
    getSizingMode(): ComponentSizingMode;
    /**
     * **Optimization**
     *
     * Should return `true` if this component covers the entire `visibleRect`
     * and would prevent anything below this component from being visible.
     *
     * Should return `false` otherwise.
     */
    occludesEverythingBelowWhenRenderedInRect(_visibleRect: Rect2): boolean;
    /** Called when this component is added to the given image. */
    onAddToImage(_image: EditorImage): void;
    onRemoveFromImage(): void;
    /**
     * Renders this component onto the given `canvas`.
     *
     * If `visibleRect` is given, it should be the region of `canvas` that is visible --
     * rendering anything outside of `visibleRect` should have no visible effect on the
     * resultant image.
     *
     * For optimal performance, implementers should call `canvas.startObject` and `canvas.endObject`
     * before and after rendering.
     */
    abstract render(canvas: AbstractRenderer, visibleRect?: Rect2): void;
    /** @return true if `lineSegment` intersects this component. */
    abstract intersects(lineSegment: LineSegment2): boolean;
    /**
     * @returns true if this component intersects `rect` -- it is entirely contained
     *  within the rectangle or one of the rectangle's edges intersects this component.
     *
     * The default implementation assumes that `this.getExactBBox()` returns a tight bounding box
     * -- that any horiziontal/vertical line that intersects this' boounding box also
     * intersects a point in this component. If this is not the case, components must override
     * this function.
     */
    intersectsRect(rect: Rect2): boolean;
    /**
     * Returns a selection of points within this object. Each contiguous section
     * of this object should have a point in the returned array.
     *
     * Subclasses should override this method if the center of the bounding box is
     * not contained within the object.
     */
    keyPoints(): Point2[];
    isSelectable(): boolean;
    isBackground(): boolean;
    getProportionalRenderingTime(): number;
    protected abstract applyTransformation(affineTransfm: Mat33): void;
    /**
     * Returns a command that, when applied, transforms this by [affineTransfm] and
     * updates the editor.
     *
     * The transformed component is also moved to the top (use
     * {@link AbstractComponent#setZIndexAndTransformBy} to avoid this behavior).
     */
    transformBy(affineTransfm: Mat33): SerializableCommand;
    setZIndex(newZIndex: number): SerializableCommand;
    /**
     * Combines {@link transformBy} and {@link setZIndex} into a single command.
     *
     * @param newZIndex - The z-index this component should have after applying this command.
     * @param originalZIndex - @internal The z-index the component should revert to after unapplying
     *                         this command.
     */
    setZIndexAndTransformBy(affineTransfm: Mat33, newZIndex: number, originalZIndex?: number): SerializableCommand;
    private static transformElementCommandId;
    private static TransformElementCommand;
    /**
     * @return a description that could be read by a screen reader
     *     (e.g. when adding/erasing the component)
     */
    abstract description(localizationTable: ImageComponentLocalization): string;
    protected abstract createClone(): AbstractComponent;
    clone(): AbstractComponent;
    /**
     * Creates a copy of this component with a particular `id`.
     * This is used internally by {@link Duplicate} when deserializing.
     *
     * @internal -- users of the library shouldn't need this.
     */
    cloneWithId(cloneId: string): AbstractComponent;
    /**
     * **Optional method**: Divides this component into sections roughly along the given path,
     * removing parts that are roughly within `shape`.
     *
     * **Notes**:
     * - A default implementation may be provided for this method in the future. Until then,
     *   this method is `undefined` if unsupported.
     *
     * `viewport` should be provided to determine how newly-added points should be rounded.
     */
    withRegionErased?(shape: Path, viewport: Viewport): AbstractComponent[];
    protected abstract serializeToJSON(): any[] | Record<string, any> | number | string | null;
    serialize(): {
        name: string;
        zIndex: number;
        id: string;
        loadSaveData: LoadSaveDataTable;
        data: string | number | any[] | Record<string, any>;
    };
    private static isNotDeserializable;
    static deserialize(json: any): AbstractComponent;
}
