import { DefineComponent } from '@vue/runtime-core';
import { Ref } from 'vue-demi';
import { init } from 'echarts/core';
import { SetOptionOpts, ECElementEvent, ElementEvent } from 'echarts';

type InitType = typeof init;
type InitParameters = Parameters<InitType>;
type InitOptions = NonNullable<InitParameters[2]>;

type UpdateOptions = SetOptionOpts;

type EChartsType = ReturnType<InitType>;

type SetOptionType = EChartsType["setOption"];
type Option = Parameters<SetOptionType>[0];

type MouseEventName =
  | "click"
  | "dblclick"
  | "mouseout"
  | "mouseover"
  | "mouseup"
  | "mousedown"
  | "mousemove"
  | "contextmenu"
  | "globalout";

type ElementEventName =
  | MouseEventName
  | "mousewheel"
  | "drag"
  | "dragstart"
  | "dragend"
  | "dragenter"
  | "dragleave"
  | "dragover"
  | "drop";

type ZRenderEventName = `zr:${ElementEventName}`;

type OtherEventName =
  | "highlight"
  | "downplay"
  | "selectchanged"
  | "legendselectchanged"
  | "legendselected"
  | "legendunselected"
  | "legendselectall"
  | "legendinverseselect"
  | "legendscroll"
  | "datazoom"
  | "datarangeselected"
  | "graphroam"
  | "georoam"
  | "treeroam"
  | "timelinechanged"
  | "timelineplaychanged"
  | "restore"
  | "dataviewchanged"
  | "magictypechanged"
  | "geoselectchanged"
  | "geoselected"
  | "geounselected"
  | "axisareaselected"
  | "brush"
  | "brushEnd"
  | "brushselected"
  | "globalcursortaken";

type MouseEmits = {
  [key in MouseEventName]: (params: ECElementEvent) => boolean;
};

type ZRenderEmits = {
  [key in ZRenderEventName]: (params: ElementEvent) => boolean;
};

type OtherEmits = {
  [key in OtherEventName]: null;
};

type Emits = MouseEmits &
  OtherEmits & {
    rendered: (params: { elapsedTime: number }) => boolean;
    finished: () => boolean;
  } & ZRenderEmits;

/* eslint-disable @typescript-eslint/ban-types */


declare const LOADING_OPTIONS_KEY = "ecLoadingOptions";
declare const THEME_KEY = "ecTheme";
declare const INIT_OPTIONS_KEY = "ecInitOptions";
declare const UPDATE_OPTIONS_KEY = "ecUpdateOptions";

declare type ChartProps = {
  loading?: boolean;
  loadingOptions?: Record<string, unknown>;
  autoresize?: boolean;
  option?: Option;
  theme?: string | Record<string, unknown>;
  initOptions?: InitOptions;
  updateOptions?: UpdateOptions;
  group?: string;
  manualUpdate?: boolean;
};

type MethodNames =
  | "getWidth"
  | "getHeight"
  | "getDom"
  | "getOption"
  | "resize"
  | "dispatchAction"
  | "convertToPixel"
  | "convertFromPixel"
  | "containPixel"
  | "getDataURL"
  | "getConnectedDataURL"
  | "appendData"
  | "clear"
  | "isDisposed"
  | "dispose"
  | "setOption";

declare type ChartMethods = Pick<EChartsType, MethodNames>;

declare const Chart: DefineComponent<
  ChartProps,
  {
    root: Ref<HTMLElement | undefined>;
    chart: Ref<EChartsType | undefined>;
  },
  {},
  {},
  ChartMethods,
  {},
  {},
  Emits
>;

export { INIT_OPTIONS_KEY, LOADING_OPTIONS_KEY, THEME_KEY, UPDATE_OPTIONS_KEY, Chart as default };
