import StandardDuctIcon from "assets/mining/standardDuct.png";
import ConnectionDuctIcon from "assets/mining/connectionDuct.png";
import { pond } from "protobuf-ts/pond";
import { cloneDeep } from "lodash";
import { or } from "utils";
import { Circle } from "./Circle";

export class Block {
  public settings: pond.BlockSettings = pond.BlockSettings.create();
  public img: HTMLImageElement | undefined = undefined;
  public selected = false;
  public mouseOffsetX = 0;
  public mouseOffsetY = 0;
  public circle = Circle.create(0, 0, 0);
  public startSnap: Block | undefined = undefined;
  public endSnap: Block | undefined = undefined;

  public ctrl = false;
  public shift = false;

  public static create(pb?: pond.Block, img?: HTMLImageElement): Block {
    let my = new Block();
    my.img = new Image();
    if (pb) {
      my.settings = pond.BlockSettings.fromObject(cloneDeep(or(pb.settings, {})));
      // For some reason, negative x and y values don't clone correctly
      if (pb.settings) {
        my.settings.x = pb.settings.x;
        my.settings.y = pb.settings.y;
      }
      if (!img) {
        switch (my.settings.type) {
          case pond.BlockType.BLOCK_TYPE_VENT:
            my.img.src = StandardDuctIcon;
            break;
          case pond.BlockType.BLOCK_TYPE_VENT_CORNER:
            my.img.src = ConnectionDuctIcon;
            break;
          default:
            my.img = undefined;
        }
      } else {
        my.img = img;
      }
    }
    my.ctrl = false;
    my.shift = false;
    return my;
  }

  public static any(data: any): Block {
    return Block.create(pond.Block.fromObject(cloneDeep(data)));
  }

  public draw(context: CanvasRenderingContext2D, offsetX?: number, offsetY?: number) {
    let x = this.settings.x;
    let y = this.settings.y;
    let width = this.settings.width;
    let height = this.settings.height;

    if (this.img) {
      switch (this.settings.type) {
        case pond.BlockType.BLOCK_TYPE_NONE:
          context.fillStyle = "rgba(150, 150, 255, 150)";
          context.fillRect(x - (offsetX ? offsetX : 0), y - (offsetY ? offsetY : 0), width, height);
          break;
        default:
          context.fillStyle = "rgba(255, 255, 255, 255)";
          context.drawImage(
            this.img,
            x - (offsetX ? offsetX : 0),
            y - (offsetY ? offsetY : 0),
            width,
            height
          );
      }
    } else {
      context.fillStyle = "rgba(150, 150, 255, 150)";
      context.fillRect(x - (offsetX ? offsetX : 0), y - (offsetY ? offsetY : 0), width, height);
    }
  }

  public highlight(context: CanvasRenderingContext2D, offsetX?: number, offsetY?: number) {
    let x = this.settings.x;
    let y = this.settings.y;
    let width = this.settings.width;
    let height = this.settings.height;

    context.strokeStyle = "rgba(247, 202, 24, 1)";
    context.strokeRect(x - (offsetX ? offsetX : 0), y - (offsetY ? offsetY : 0), width, height);
  }

  public static clone(other?: Block): Block {
    if (other) {
      let b = Block.create(
        pond.Block.fromObject({
          settings: cloneDeep(other.settings),
          img: new Image()
        })
      );
      if (b.img)
        switch (b.settings.type) {
          case pond.BlockType.BLOCK_TYPE_VENT:
            b.img.src = StandardDuctIcon;
            break;
          case pond.BlockType.BLOCK_TYPE_VENT_CORNER:
            b.img.src = ConnectionDuctIcon;
            break;
          default:
            b.img = undefined;
        }
      return b;
    }
    return Block.create();
  }

  public clone() {
    return Block.create(
      pond.Block.fromObject({
        settings: cloneDeep(this.settings),
        img: undefined
      })
    );
  }

  public clickCheck(x: number, y: number, extend?: number) {
    extend = extend ? extend : 0;
    if (
      x > this.x() - extend &&
      x < this.x() + this.width() + extend * 2 &&
      y > this.y() - extend &&
      y < this.y() + this.height() + extend * 2
    ) {
      this.selected = true;
      this.mouseOffsetX = x - this.x();
      this.mouseOffsetY = y - this.y();
      return true;
    }
    this.selected = false;
    return false;
  }

  public x(): number {
    return this.settings.x;
  }

  public endX(): number {
    return this.settings.x + this.settings.width;
  }

  public y(): number {
    return this.settings.y;
  }

  public endY(): number {
    return this.settings.y + this.settings.height;
  }

  public width(): number {
    return this.settings.width;
  }

  public height(): number {
    return this.settings.height;
  }

  public getCtrl(): boolean {
    return this.ctrl;
  }

  public setCtrl(c: boolean) {
    this.ctrl = c;
  }

  public getShift(): boolean {
    return this.shift;
  }

  public setShift(s: boolean) {
    this.shift = s;
  }

  public setSelected(s: boolean) {
    this.selected = false;
  }

  public radians(ang?: number) {
    let angle = ang ? ang : this.settings.angle;
    return angle * (Math.PI / 180);
  }

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

  public getSnap(rect: Block, snapDistance?: number) {
    snapDistance = snapDistance ? snapDistance : 6;
    let rect1 = this;
    let rect2 = rect;

    // Check top right corner of moving square with top left of square 2
    let x2 = rect2.x();
    let y2 = rect2.y();
    let x = rect1.x();
    let y = rect1.y();
    let d = this.distance(rect1.x() + rect1.width(), rect2.x(), rect1.y(), y2);
    if (d < snapDistance) {
      return {
        x: x2 - rect1.width(),
        y: y2
      };
    }

    // Top left corner of moving square vs top right corner
    d = this.distance(x, x2 + rect2.width(), y, y2);
    if (d < snapDistance) {
      return {
        x: x2 + rect2.width(),
        y: y2
      };
    }

    // Bottom left corner of moving square vs top left corner
    d = this.distance(x, x2, y, y2 - rect2.height());
    if (d < snapDistance) {
      return {
        x: x2,
        y: y2 - rect2.height()
      };
    }

    // Top left corner of moving square vs bottom left corner
    d = this.distance(x, x2, y, y2 + rect2.height());
    if (d < snapDistance) {
      return {
        x: x2,
        y: y2 + rect2.height()
      };
    }
  }

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

  /*public drag = (e: any, offsetX?: number, offsetY?: number) => {
    let x = e.pageX - (e.currentTarget.offsetLeft + e.currentTarget.clientLeft) - mouseOffsetX;
    x = x - getOffsetX(e.currentTarget.offsetParent) + cameraOffsetX;
    selected[0].settings.x = x;
    let y = e.pageY - (e.currentTarget.offsetTop + e.currentTarget.clientTop) - mouseOffsetY;
    y = y - getOffsetY(e.currentTarget.offsetParent) + cameraOffsetY;
    selected[0].settings.y = y;
  }*/
}
