import { Vector3, Intersection, Object3D, Event, Scene, PerspectiveCamera, WebGLRenderer } from 'three';
import { Group } from '@tweenjs/tween.js';
import CameraControls from 'camera-controls';
import { Handler, EventType, Emitter } from 'mitt';

declare class MyCameraControls extends CameraControls {
    truckYDisabled: boolean;
    _truckInternal: (deltaX: any, deltaY: any, dragToOffset: any) => void;
}

interface IStyle {
    normal: any;
    dark: any;
}
declare type IViewMode = '2D' | '2d' | '3D' | '3d';
interface IOptions {
    style?: keyof IStyle;
    showStats?: boolean;
    viewMode?: IViewMode;
}
interface PickUp {
    worldPosition?: Vector3;
    screenPosition?: {
        x: number;
        y: number;
    };
    intersects?: Intersection<Object3D<Event>>[];
}
declare type Events = {
    /**
     * 点击
     */
    click: MouseEvent & PickUp;
    /**
     * 鼠标移动
     */
    mousemove: MouseEvent & PickUp;
};
interface Info {
    /**
     * fitDistance
     */
    fitDistance: number;
    boundingClientRect: Omit<DOMRect, 'toJSON'>;
}

declare class _Map {
    container: string;
    options: IOptions;
    private stats?;
    scene: Scene;
    camera: PerspectiveCamera;
    $map: HTMLElement;
    renderer: WebGLRenderer;
    domElement: HTMLElement;
    updateSizeMap: Map<any, () => void>;
    tweenGroupMap: Map<Group, unknown>;
    private emitter;
    private timer;
    private viewChanged;
    cameraControls: MyCameraControls;
    /**
     * 存储 map 的一些相关信息
     */
    info: Info;
    constructor(container: string, { style, showStats, viewMode }?: IOptions);
    /**
     * 生成图片
     */
    generateImage(type?: string, quality?: number): string;
    getScene(): Scene;
    /**
     * @desc 二封 scene.add
     * to do：
     * - 需要判断新增的 layer 是否重名，判断 name 属性
     */
    add(...objects: ElementType[keyof ElementType][]): this;
    remove(...object: ElementType[keyof ElementType][]): void;
    on<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>): this;
    off<Key extends keyof Events>(type: Key, handler?: Handler<Events[Key]>): this;
    /**
     * @desc 重渲染，为了提高性能，往场景添加元素，需要调用 redraw
     * 箭头函数，保证 this 指向正确
     */
    reDraw: (time?: number) => void;
    /**
     * @desc 初始化地图：场景，相机，灯光，渲染器，rendererResize，轨道控制器
     */
    private init;
    /**
     * @desc 相机控制器
     */
    private createCameraControls;
    /**
     * @desc 恢复到相机的初始状态
     */
    reset(): this;
    destroy(): void;
    /**
     * @desc 添加地图上的辅助对象，如灯光线条或者
     */
    addHelper(): this;
    setStyle(style: keyof IStyle): this;
    setShowStats(showStats: boolean): this;
    setViewMode(viewMode: IViewMode): this;
    fitToBox2d(): void;
    fitToBox3d(): void;
}

interface ElementType {
    Object3D: THREE.Object3D;
}

interface KTMap$1 {
    Map: typeof _Map;
    use(plugins: Plugins): this;
}
declare type Plugins = (new (...args: any[]) => Element<any> | Service<any> | Control<any> | InfoWindow<any>) | Array<new (...args: any[]) => Element<any> | Service<any> | Control<any> | InfoWindow<any>>;

/**
 * mitt 事件总程
 */
declare class MyMitt<T extends Record<EventType, unknown>> {
    protected emitter: Emitter<T>;
    constructor();
    on<Key extends keyof T>(type: Key, handler: Handler<T[Key]>): this;
    off<Key extends keyof T>(type: Key, handler?: Handler<T[Key]>): this;
}

/**
 * 基类，element
 *
 * 被添加到地图上的元素
 *
 * 若当前扩展类不需要 mitt，在继承时，泛型填写 any，如：
 *
 * ```ts
 * class Foo extends Element<any>{
 *
 * }
 * ```
 */
declare abstract class Element<T extends Record<EventType, unknown>> extends MyMitt<T> {
    /**
     * NAME
     * 一般为子类的类名（防止工具压缩把类名压缩了，导致一些拿类名判断的逻辑失效，所以手动加上类名）
     */
    protected map: _Map;
    constructor();
    /**
     * __inject
     * 当元素被 map.add 之后，会注入整个 map 对象到子类，提供子类使用 map
     */
    __inject(map: _Map): this;
    /**
     * 子类初始化方法
     */
    abstract __init(): void;
}

/**
 * TODO:Control 基类，待实现
 */
declare abstract class Control<T extends Record<EventType, unknown>> extends MyMitt<T> {
    protected map: _Map;
    constructor();
    __inject(map: _Map): this;
    abstract __init(): void;
    /**
     * 插件加载结束的回调函数（成功、失败都会执行）
     */
    abstract complete(): void;
}

/**
 * Service 服务类
 */
declare abstract class Service<T extends Record<EventType, unknown>> extends MyMitt<T> {
    constructor();
    abstract __init(): void;
}

/**
 * 信息窗体
 */
declare abstract class InfoWindow<T extends Record<EventType, unknown>> extends MyMitt<T> {
    constructor();
    abstract __init(): void;
}

/**
 * 右键菜单
 */
declare abstract class ContextMenu {
    constructor();
    abstract __init(): void;
}

declare const KTMap: KTMap$1;

export { ContextMenu, Control, Element, ElementType, InfoWindow, KTMap$1 as KTMap, _Map as Map, MyMitt, Service, KTMap as default };
