import { ViewProps } from "./components";
import {
  NativeKrpanoRendererObject,
  ROTATE_DIRECTION,
  ZOOM_ACTION,
} from "./types";
import { buildKrpanoAction, buildKrpanoTagSetterActions } from "./utils";

declare global {
  interface Window {
    ReactKrpanoActionProxy?: KrpanoActionProxy;
  }
}

export type HandlerFunc = (renderer: KrpanoActionProxy) => void;

interface EventHandler {
  eventName: string;
  selector: string;
  handler: HandlerFunc;
}

export class KrpanoActionProxy {
  name: string;
  krpanoRenderer?: NativeKrpanoRendererObject;
  eventHandlers: EventHandler[] = [];

  constructor(
    krpanoRenderer?: NativeKrpanoRendererObject,
    name = "ReactKrpanoActionProxy"
  ) {
    this.krpanoRenderer = krpanoRenderer;
    this.name = name;
  }

  call(action: string, nexttick = false): void {
    const actionStr = nexttick ? `nexttick(${action})` : action;

    this.krpanoRenderer?.call(actionStr);
  }

  set(name: string, ...params: Array<string | number | boolean>): void {
    this.call(buildKrpanoAction("set", name, ...params));
  }

  setTag(
    tag: "scene" | "hotspot" | "layer" | "view" | "events",
    name: string | null,
    attrs: Record<string, string | boolean | number | undefined>
  ): void {
    let nexttick = false;

    if (tag === "hotspot" || tag === "events") {
      nexttick = true;
    }

    this.call(
      buildKrpanoTagSetterActions(name ? `${tag}[${name}]` : tag, attrs),
      nexttick
    );
  }

  get<T = any>(name: string): T {
    return this.krpanoRenderer?.get(name);
  }

  removeScene(name: string): void {
    if (
      this.get("scene") &&
      typeof this.get("scene").removeItem === "function"
    ) {
      this.get("scene").removeItem(name);
    } else {
      // TODO: report Error
    }
  }

  /**
   * 加载场景
   * @param name 场景 name
   */
  loadScene(name: string): void {
    this.call(
      buildKrpanoAction("loadscene", name, "null", "MERGE", "BLEND(0.5)")
    );
  }

  /**
   * 旋转视图
   * @param direction 方位
   * @param degrees 旋转度数，默认为 10
   */
  rotateView(direction: ROTATE_DIRECTION, degrees = 10) {
    let str = "";
    const view: ViewProps = this.get("view");

    switch (direction) {
      case ROTATE_DIRECTION.LEFT:
        str = `view.hlookat, ${(view.hlookat || 0) - degrees}`;
        break;
      case ROTATE_DIRECTION.RIGHT:
        str = `view.hlookat, ${(view.hlookat || 0) + degrees}`;
        break;
      case ROTATE_DIRECTION.UP:
        str = `view.vlookat, ${(view.vlookat || 0) - degrees}`;
        break;
      case ROTATE_DIRECTION.DOWN:
        str = `view.vlookat, ${(view.vlookat || 0) + degrees}`;
        break;
    }

    this.call(buildKrpanoAction("tween", str, 0.5));
  }

  /**
   * 缩放视图
   * @param action 动作
   * @param num 缩放大小
   */
  zoomView(action: ZOOM_ACTION, num = 10) {
    const view: ViewProps = this.get("view");
    const targetFov = action === ZOOM_ACTION.IN ? -num : num;

    this.call(
      buildKrpanoAction("tween", "view.fov", (view.fov || 0) + targetFov, 1)
    );
  }
}
