import * as THREE from "three";
import { DxfChange } from "./DxfCompare";
import { DxfObject } from "./DxfObject";
import { Units } from "../../core/Units";
import { IBlock, IDxf, IEntity, ILayer, ILayoutObject, IPoint, IViewport, IViewportEntity, TableCell } from "../../core/dxf-parser";
import { ImageFlags } from "../../core/dxf-parser/entities/image";
import { IMLeaderContextData } from "../../core/dxf-parser/entities/mleader";
import { ISpatialFilterObject } from "../../core/dxf-parser/objects/spatialfilter";
import { FontManager } from "../../core/font";
/**
 * @hidden
 */
export interface DxfData extends IDxf {
    /**
     * Root object for the entire drawing.
     */
    threejsObject: THREE.Object3D;
    /**
     * Organizes threejs objects by layer name. The key is layer name.
     */
    layersAndThreejsObjects: Record<string, THREE.Object3D[]>;
    /**
     * Created/loaded entity count. Mainly for log usage, not an accurate value.
     * We cannot get this value from threejsObject because it may be merged.
     */
    loadedEntityCount: number;
    /**
     * Layout and viewports map. The key is layout's paperSpaceTableId (usually equal to layout's ownerHandle).
     */
    layoutViewportsMap: Record<string, IViewportEntity[]>;
}
/**
 * Dxf/dwg layer, which contains a number of objects in it.
 *
 * A layer has "name", "handle", "color", "visible" and many other properties.
 *
 * We can change a layer's visibility, color, etc.
 */
export type DxfLayer = ILayer;
/**
 * Dxf entity, which can be an arc, circle, attach, line, insert, text, etc.
 * @hidden
 */
export interface DxfEntity extends IEntity {
    threejsObject?: THREE.Object3D;
    dimStyleName: string;
    dimensionType?: number;
    anchorPoint?: THREE.Vector3;
    block?: string;
    majorAxisEndPoint?: THREE.Vector2 | THREE.Vector3;
    axisRatio?: number;
    center?: THREE.Vector3;
    startAngle?: number;
    endAngle?: number;
    style?: number;
    text?: string;
    height?: number;
    width?: number;
    position?: THREE.Vector3;
    blockPosition?: IPoint;
    rotation?: number;
    directionVector?: THREE.Vector3;
    attachmentPoint?: number;
    drawingDirection?: number;
    controlPoints?: IPoint[];
    degree?: number;
    knots?: number[];
    numberOfControlPoints: number;
    fitPoints?: IPoint[];
    vertices?: IPoint[];
    shape: boolean;
    isPolyfaceMesh: boolean;
    pathType: number;
    direction: number;
    hasHookline: boolean;
    textWidth: number;
    dimensionStyle: string;
    arrowFlag: number;
    arrowHeight: number;
    arrowHeadScale: number;
    arrowHeadBlockHandle: string;
    contextData?: IMLeaderContextData;
    enableDogLeg: boolean;
    leaderLineType: number;
    arrowHeadId: string;
    arrowHeadSize: number;
    radius?: number;
    points?: THREE.Vector3[];
    startPoint?: THREE.Vector3;
    endPoint?: THREE.Vector3;
    textHeight: number;
    halign?: number;
    valign?: number;
    mirrored?: number;
    textStyle?: string;
    lineSpaceFactor?: number;
    name?: string;
    xScale?: number;
    yScale?: number;
    zScale?: number;
    elevation?: number;
    extrusionDirectionX?: number;
    extrusionDirectionY?: number;
    extrusionDirectionZ?: number;
    extrusionDirection?: {
        z: number;
    };
    entities?: IEntity[];
    tag?: string;
    prompt?: string;
    scale?: number;
    preset: boolean;
    invisible: boolean;
    documentType?: string;
    version?: number;
    leftUpX?: number;
    leftUpY?: number;
    leftUpZ?: number;
    rightDownX?: number;
    rightDownY?: number;
    rightDownZ?: number;
    tileModeDescriptor?: number;
    binaryData?: string;
    dataSize?: number;
    image: string;
    psBBox?: THREE.Box3;
    msToPsMatrix?: THREE.Matrix4;
    viewportThreejsObject?: DxfObject;
    associatedLeafObjectSet?: Set<THREE.Object3D>;
    imageSize?: IPoint;
    imageDefHandle?: string;
    uPixel?: IPoint;
    vPixel?: IPoint;
    flags?: ImageFlags;
    columnCount: number;
    rowCount: number;
    cells: TableCell[];
    rowHeightArr: number[];
    columnWidthArr: number[];
    blockRecordHandle?: string;
}
/**
 * Dxf block.
 * @hidden
 */
export interface DxfBlock extends IBlock {
    /**
     * References to corresponding threejs object
     */
    threejsObject?: DxfObject;
}
/**
 * Dxf layout.
 * @hidden
 */
export interface DxfLayout extends ILayoutObject {
    /**
     * A collection of leaf objects directly associated with the layout, used for subsequent selection and measurement, etc.
     * "Model" space doesn't need it for now.
     */
    directAssociatedLeafObjectSet?: Set<THREE.Object3D>;
}
/**
 * Spatial filter clip polyline.
 * @hidden
 */
export interface DxfSpatialFilterClipPolyline {
    polyline: THREE.Vector3[];
    bConcave: boolean;
    bReversed: boolean;
}
/**
 * Spatial filter.
 * @hidden
 */
export interface DxfSpatialFilter extends ISpatialFilterObject {
    /**
     * References to corresponding threejs object
     */
    threejsObject?: DxfObject;
    localMatrix?: THREE.Matrix4;
    clipPolylines: DxfSpatialFilterClipPolyline[];
}
/**
 * Dxf loader config.
 * @hidden
 */
export interface DxfLoaderConfig {
    /**
     * Ignores everything from paper space, aka, only load model space.
     */
    ignorePaperSpace?: boolean;
    /**
     * Enables caching dxf data into indexeddb.
     */
    enableLocalCache?: boolean;
    /**
     * Enables to release data after loaded in order to improve preformance.
     * @hidden
     */
    enableReleaseData?: boolean;
    /**
     * Enables to merge objects.
     */
    enableMerge?: boolean;
    /**
     * File encoding, can be used by dxf. Common encoding include "UTF-8", "gb2312", etc.
     */
    encoding?: string;
    /**
     * Apply this color to everything in this model.
     * Color value between 0 and 1.
     */
    overrideColor?: number[];
    /**
     * Idealy, the thickness of lines in hatch pattern should always be 1 pixel.
     * In Viewer2d, it uses orthographic camera and always in top view,
     * so we adjust thickness by cameraZoom (and also consider worldScale).
     * While 3d view is more complex, it can use perspective camera,
     * its camera position and direction is flexible. We cannot keep line thickness
     * in a fixed pixel any more, and there is no proper way to adjust thickness as
     * position changes. So, we need to use a fixed thickness in world coordinates.
     */
    overrideHatchPatternLineThickness?: number;
}
/**
 * Dxf file loader.
 * @hidden
 */
export declare class DxfLoader extends THREE.Loader {
    static readonly MODEL_LAYOUT_NAME = "Model";
    static readonly SNAP_GROUP_NAME = "InvisibleObjectGroupForOSnap";
    static readonly SHOW_SNAP_OBJECT = false;
    font?: FontManager;
    angBase: string | number | IPoint;
    angDir: string | number | IPoint;
    static CameraZoomUniform: {
        value: number;
    };
    /**
     * Used for drawing dashed lines properly in a viewport.
     */
    static ViewportScaleUniform: {
        value: number;
    };
    static TransformMatrixUniform: {
        value: THREE.Matrix4;
    };
    static ResolutionUniform: {
        value: THREE.Vector2;
    };
    /**
     * WebGL has a limited capability for FragmentUniforms. Thus, cannot have as many
     * clippingPlanes as expected.
     */
    static MaxFragmentUniforms: number;
    /**
     * DxfLoader constructor
     */
    constructor(manager?: THREE.LoadingManager, cfg?: DxfLoaderConfig);
    /**
     * Sets font.
     */
    setFont(font: FontManager): void;
    /**
     * Loads dxf asynchronously. It mainly contains 2 steps:
     * 1. Parses file content
     * 2. Generates/load threejs objects
     * @param url url of the dxf file
     * @param onProgress on progress callback
     */
    loadAsync(url: string, onProgress?: (event: ProgressEvent) => void, dxfDataId?: string): Promise<DxfData>;
    /**
     * Same as {@link loadAsync} but reads DWG/DXF from memory (no network).
     */
    loadAsyncFromBuffer(data: ArrayBuffer | Uint8Array, onProgress?: (event: ProgressEvent) => void, dxfDataId?: string): Promise<DxfData>;
    /**
     * Parses dxf contents from given url.
     */
    parse(url: string, onProgress?: (event: ProgressEvent) => void): Promise<IDxf>;
    /**
     * Parses DWG/DXF from memory (same pipeline as {@link parse} after download).
     */
    parseFromBuffer(data: ArrayBuffer | Uint8Array, onProgress?: (event: ProgressEvent) => void): Promise<IDxf>;
    /**
     * Generates/load threejs objects according to the dxf data.
     * @param data
     * @param onProgress
     * @returns the promise of DxfData
     */
    loadEntities(data: IDxf, onProgress?: (event: ProgressEvent) => void): Promise<DxfData>;
    /**
     * Loads entities from two dxf data for comparing.
     * It also generates DxfChange information for each change.
     */
    loadEntitiesForCompare(data1: IDxf, data2: IDxf, changes: Record<string, DxfChange>, bIgnoreSameEntity?: boolean, onProgress?: (event: ProgressEvent) => void): Promise<void>;
    /**
     * Sets override colors for DXF compare visualization.
     * If not set, {@link DxfCompare.ENTITY_COLOR_ADDED} and
     * {@link DxfCompare.ENTITY_COLOR_REMOVED} will be used.
     */
    setCompareColors(addedColor?: THREE.Color, removedColor?: THREE.Color): void;
    /**
     * We'll need to pass in the blockEntity when loadEntity is called from a block.
     * So that, when an entity's color is ByLayer, and its layer is "0", it should use block's layer,
     * rather than the layer of the entity itself!
     * We don't know if there is other similar case in future, so pass in blockEntity here.
     */
    loadEntity(entity: DxfEntity, data: IDxf, parentEntity?: IEntity, isParentChanged?: boolean): DxfObject | undefined;
    static updateMaterialUniforms(material: THREE.Material): void;
    static transformAngleByOcsMatrix(ocsMatrix: THREE.Matrix4, angle: number): number;
    static getArcAnglesByOcsMatrix(ocsMatrix: THREE.Matrix4, startAngle: number, endAngle: number): number[];
    static getDcs2WcsMatrix(viewportEntity: IViewportEntity | IViewport, angDir: number): THREE.Matrix4;
    /**
     * Gets a proper interpolation for bspline.
     * A bigger interpolation value generates smooth bspline, but with a bad performance, so we need to limit this value.
     * @param pointCount control point count
     * @param size may not be accurate, can be the long side of bbox, etc.
     */
    getBSplineInterpolationsPerSplineSegment(pointCount: number, size: number): number;
    static getDxfUnits(unitValue: number): Units;
    /**
     * Calculates line distances for given line in world space.
     */
    static computeLineDistance(line: THREE.Line): void;
    /**
     * Calculates line distances for all lines of an object in world space.
     * We need to call this before rendering dashed lines (before calling createLineShaderMaterial).
     */
    static computeLineDistances(object: THREE.Object3D): void;
    /**
     * Merges objects by layer and layout.
     */
    static merge(dxfData: DxfData, onProgress?: (event: ProgressEvent) => void): Promise<void>;
}
