import { EventKey } from "@egjs/component/declaration/types";
import { ReactiveEventCallback } from "./types";
import { ReactiveSubscribe } from "./ReactiveSubscribe";

export interface ReactiveAdapter<
  Instance extends ReactiveSubscribe<Record<string, any>>,
  State extends Record<string, any> = {},
  Methods extends keyof Partial<Instance> = never,
  Data = any,
  Events extends Record<string, any> = {},
  > {
  /**
   * Specify if you want to use the framework's state. If an instance is created through created, it can be omitted.
   */
  state?: State;
  /**
   * If you want to use an instance's method, write the method names.
   */
  methods?: readonly Methods[];
  /**
   * If you want to use events, write the events property and a way to register/unregister events.
   */
  events?: readonly (keyof Events)[];
  /**
   * You can decide which data to pass when creating/destroying instances in the framework.
   */
  data?: () => Data;
  /**
   * Occurs when a component is created.
   * If an instance is created and returned, the state specification can be omitted.
   * @return Instance
   */
  created?: (data: Data) => Instance | undefined | void;
  /**
   * Occurs when a component is mounted.
   * @return Instance
   */
  mounted?: (data: Data) => Instance | undefined | void;
  /**
   * Occurs after mount, state declaration, and observation in the component.
   */
  init?: (instance: Instance, data: Data) => void;
  /**
   * Occurs before the component is destroyed.
   */
  destroy?: (instance: Instance, data: Data) => void;
  /**
   * If you want to use events, write the events property and a way to register/unregister events.
   */
  on?: <EventName extends EventKey<Events>>(instance: Instance, eventName: EventName, listener: ReactiveEventCallback<Events, EventName>) => void;
  /**
   * If you want to use events, write the events property and a way to register/unregister events.
   */
  off?: <EventName extends EventKey<Events>>(instance: Instance, eventName: EventName, listener: ReactiveEventCallback<Events, EventName>) => void;
}
