import { pond } from "protobuf-ts/pond";
import { Placeable } from "./Placeable";
import Fan1Icon from "assets/editor/fan1.png";
import Fan2Icon from "assets/editor/fan2.png";
import Fan3Icon from "assets/editor/fan3.png";
import { or } from "utils";
import { SnapPoint } from "./geometry";

export class Fan implements Placeable {
  public angle: number = 0;
  public ctrl: boolean = false;
  public shift: boolean = false;
  public direction = 0;
  //public snapPoints = []
  private mouseOffsetX = 0;
  private mouseOffsetY = 0;
  type: pond.PlaceableType = pond.PlaceableType.PLACEABLE_TYPE_FAN;
  public subtype = 0;

  magnitude(): number {
    return 0;
  }

  radius(): number {
    return this.fan_radius;
  }

  highlight(
    context: CanvasRenderingContext2D,
    offsetX?: number,
    offsetY?: number,
    scale = 1
  ): void {
    offsetX = offsetX ? offsetX : 0;
    offsetY = offsetY ? offsetY : 0;

    let x = (this.x - offsetX) * scale;
    let y = (this.y - offsetY) * scale;

    context.beginPath();
    context.strokeStyle = "yellow";
    context.arc(x, y, this.radius() * scale, 0, 2 * Math.PI);
    context.stroke();

    context.strokeStyle = "white";
  }

  public drag = (x: number, y: number) => {
    this.x = x - this.mouseOffsetX;
    this.y = y - this.mouseOffsetY;
  };

  public getEndXAndY = (x = this.x, y = this.y, angle = this.angle, length = this.magnitude()) => {
    return { x: x, y: y };
  };

  getSnapPoints() {
    let snaps: SnapPoint[] = [];
    snaps.push({
      x: this.x,
      y: this.y,
      angle: this.angle,
      startPoint: false,
      occupant: undefined
    } as SnapPoint);
    return snaps;
  }

  snap(p: Placeable, d: number): void {
    d = d ? d : 12;
    p.getSnapPoints().forEach(point => {
      if (this.distance(this.x, point.x, this.y, point.y) < d) {
        this.x = point.x;
        this.y = point.y;
        //this.angle = point.angle;
      }
    });
  }

  private fan_radius = 1;
  public x = 0;
  public y = 0;
  public selected = true;
  public img: HTMLImageElement | undefined = undefined;

  public static create(x: number, y: number, radius: number, subtype: number): Fan {
    let c = new Fan();
    let i = new Image();
    i.src = Fan1Icon;
    switch (subtype) {
      case pond.FanType.FAN_TYPE_CENTRIFUGAL_INLINE:
        i.src = Fan1Icon;
        break;
      case pond.FanType.FAN_TYPE_CENTRIFUGAL_HIGH_SPEED:
        i.src = Fan2Icon;
        break;
      case pond.FanType.FAN_TYPE_CENTRIFUGAL_LOW_SPEED:
        i.src = Fan3Icon;
        break;
    }
    c.img = i;
    c.x = x;
    c.y = y;
    c.fan_radius = radius;
    c.subtype = subtype;
    return c;
  }

  public static fromPond(placeable: pond.Placeable) {
    let f = new Fan();
    let i = new Image();
    i.src = Fan1Icon;
    if (placeable.subtype) {
      switch (placeable.subtype) {
        case pond.FanType.FAN_TYPE_CENTRIFUGAL_INLINE:
          i.src = Fan1Icon;
          break;
        case pond.FanType.FAN_TYPE_CENTRIFUGAL_HIGH_SPEED:
          i.src = Fan2Icon;
          break;
        case pond.FanType.FAN_TYPE_CENTRIFUGAL_LOW_SPEED:
          i.src = Fan3Icon;
          break;
      }
    }
    f.img = i;
    f.x = placeable.x;
    f.y = placeable.y;
    f.fan_radius = or(placeable.radius, placeable.width / 2);
    f.subtype = placeable.subtype;
    return f;
  }

  public draw(context: CanvasRenderingContext2D, offsetX?: number, offsetY?: number, scale = 1) {
    offsetX = offsetX ? offsetX : 0;
    offsetY = offsetY ? offsetY : 0;
    let oldStyle = context.fillStyle;
    if (this.img === undefined) {
      context.beginPath();
      context.arc(
        (this.x + offsetX) * scale,
        (this.y + offsetY) * scale,
        this.radius(),
        0,
        2 * Math.PI
      );
      if (this.selected) {
        context.fillStyle = "grey";
        context.fill();
      }
      context.stroke();
      context.fillStyle = oldStyle;
    } else {
      context.fillStyle = "rgba(255, 255, 255, 255)";
      context.drawImage(
        this.img,
        (this.x - (offsetX ? offsetX : 0) - this.radius()) * scale,
        (this.y - (offsetY ? offsetY : 0) - this.radius()) * scale,
        this.radius() * 2 * scale,
        this.radius() * 2 * scale
      );
    }
  }

  public distance(x1: number, x2: number, y1: number, y2: number) {
    let a = x1 - x2;
    let b = y1 - y2;
    return Math.sqrt(a * a + b * b);
  }

  public clickCheck(x: number, y: number) {
    let dx = Math.abs(x - this.x);
    let dy = Math.abs(y - this.y);
    let distance = Math.sqrt(dx * dx + dy * dy);
    if (distance <= this.radius()) {
      this.selected = true;
      this.mouseOffsetX = x - this.x;
      this.mouseOffsetY = y - this.y;
      return true;
    }
    this.selected = false;
    this.mouseOffsetX = 0;
    this.mouseOffsetY = 0;
    return false;
  }

  public clone() {
    let f = new Fan();
    f.img = this.img;
    f.radius = this.radius;
    f.selected = false;
    f.x = this.x;
    f.y = this.y;
    return f;
  }

  public getEndAngle(): number {
    return this.angle;
  }

  setDirection(direction: number): void {}

  setAngle(angle: number, oldAngle?: number) {
    this.angle = angle;
    //if (oldAngle) this.oldAngle = oldAngle
  }
}
