import { pond } from "protobuf-ts/pond";
import { Fan } from "./Fan";
import { VentCorner } from "./VentCorner";
import { VentShaft } from "./VentShaft";
import { VentTBreak } from "./VentTBreak";
import { SnapPoint } from "./geometry";

export enum Direction {
  CLOCKWISE,
  COUNTERCLOCKWISE
}

export interface Placeable {
  x: number;
  y: number;
  angle: number;
  ctrl: boolean;
  shift: boolean;
  selected: boolean;
  type: pond.PlaceableType;
  subtype: number;
  direction: number;
  magnitude(): number;
  radius(): number;
  clone(): any;
  clickCheck(x: number, y: number, scale?: number): boolean;
  highlight(
    context: CanvasRenderingContext2D,
    offsetX?: number,
    offsetY?: number,
    scale?: number
  ): void;
  drag(x: number, y: number, scale?: number): void;
  getEndXAndY(x?: number, y?: number, angle?: number, length?: number): { x: number; y: number };
  getEndAngle(): number;
  getSnapPoints(): SnapPoint[];
  snap(p: Placeable, d?: number): void;
  draw(context: CanvasRenderingContext2D, offsetX?: number, offsetY?: number, scale?: number): void;
  setDirection(direction: number | Direction): void;
  setAngle(angle: number, oldAngle?: number): void;
}

export function loadPlaceable(shaft: pond.Placeable) {
  if (shaft.direction === undefined) shaft.direction = 0;
  if (shaft.angle === undefined) shaft.angle = 0;

  // The pond may store the type as a string or number
  let type = pond.PlaceableType.PLACEABLE_TYPE_DEFAULT.valueOf();
  if (shaft.type !== undefined) {
    if (typeof shaft.type === "string") {
      type = (pond.PlaceableType[shaft.type] as unknown) as number;
    } else {
      type = +pond.PlaceableType[shaft.type];
    }
  }

  switch (type) {
    case pond.PlaceableType.PLACEABLE_TYPE_SHAFT:
      if (shaft.subtype) {
        switch (shaft.subtype) {
          case pond.ShaftType.SHAFT_TYPE_DEFAULT:
            return VentShaft.fromPond(shaft);
          case pond.ShaftType.SHAFT_TYPE_CORNER:
            return VentCorner.fromPond(shaft);
          case pond.ShaftType.SHAFT_TYPE_T_BREAK:
            return VentTBreak.fromPond(shaft);
        }
      }
      return VentShaft.fromPond(shaft);
    case pond.PlaceableType.PLACEABLE_TYPE_FAN:
      return Fan.fromPond(shaft);
    default:
      return VentShaft.fromPond(shaft);
  }
}
