/**
 * Rect
 */
export default class Rect {
  left: number;
  top: number;
  right: number;
  bottom: number;

  constructor(left: number = 0, top: number = 0, right: number = 0, bottom: number = 0) {
    this.left = left;
    this.top = top;
    this.right = right;
    this.bottom = bottom;
  }

  set(left: number, top: number, right: number, bottom: number) {
    this.left = left;
    this.top = top;
    this.right = right;
    this.bottom = bottom;
  }

  /**
   * Get width of the rect.
   */
  width() {
    return this.right - this.left + 1;
  }

  /**
   * Get height of the rect
   */
  height() {
    return this.bottom - this.top + 1;
  }

  /*
   * Get the center point of the rect.
   */
  center() {
    return {
      x: (this.right + this.left) / 2,
      y: (this.bottom + this.top) / 2
    }
  }

  /*
   * Check if point x, y in rect.
   */
  contains(x: number, y: number) {
    return x >= this.left &&
      x <= this.right &&
      y >= this.top &&
      y <= this.bottom;
  }

  /**
   * Move rect to match the center point x, y
   */
  centerTo(x: number, y: number) {
    //current center
    var center = this.center();
    this.offset(x - center.x, y - center.y);
  }

  /**
   * Offset rect by dx, dy
   */
  offset(dx: number, dy: number) {
    this.left += dx;
    this.right += dx;
    this.top += dy;
    this.bottom += dy;
  }


  /** 
   * Scale the rect at(0, 0)
   */
  scale(scale: number) {
    this.left *= scale;
    this.right *= scale;
    this.top *= scale;
    this.bottom *= scale;
  }


  /**
   * Scale the rect by certain point x,y
   */
  scaleBy(scale: number, x: number, y: number) {
    this.offset((-1) * x, (-1) * y);
    this.scale(scale);
    this.offset(x, y);
  }

  /**
   * Scale the rect by center 
   */
  scaleByCenter(scale: number) {
    var center = this.center();
    this.scaleBy(scale, center.x, center.y);
  }


  /**
   * Scale the rect to contain x, y
   */
  scaleToContain(x: number, y: number) {
    if (this.contains(x, y)) return;
    var center = this.center();
    var dx = Math.abs(x - center.x);
    var dy = Math.abs(y - center.y);
    var scale = Math.max(dx / (this.width() / 2), dy / (this.height() / 2));
    if (scale > 1) this.scaleByCenter(scale);
  }


  /**
   * Scale the rect to contain another rect. 
   */
  scaleToContainRect(rect: Rect) {
    if (rect instanceof Rect) {
      this.scaleToContain(rect.left, rect.top);
      this.scaleToContain(rect.right, rect.top);
      this.scaleToContain(rect.left, rect.bottom);
      this.scaleToContain(rect.right, rect.bottom);
    }
  }


  inset(left: number, top: number, right: number, bottom: number) {
    return new Rect(
      this.left + left,
      this.top + top,
      this.right - right,
      this.bottom - bottom
    );
  }


  /**
   *
   * Clone self.
   */
  clone() {
    return new Rect(this.left, this.top, this.right, this.bottom);
  }


}
