import { deepMix, each } from '@antv/util';
import Action from '../base';
import { LooseObject } from '../../../interface';

/**
 * @ignore
 * 辅助框 Action 的基类
 */
abstract class MaskBase extends Action {
  // mask 图形
  protected maskShape = null;
  // 组成 mask 的各个点
  protected points = [];
  // 开始 mask 的标记
  protected starting = false;
  // 开始移动的标记
  protected moving = false;
  protected preMovePoint = null;

  protected shapeType = 'path';
  // 获取当前的位置
  protected getCurrentPoint() {
    const event = this.context.event;
    return {
      x: event.x,
      y: event.y,
    };
  }
  // 触发 mask 的事件
  protected emitEvent(type) {
    const eventName = `mask:${type}`;
    const view = this.context.view;
    const event = this.context.event;
    view.emit(eventName, {
      target: this.maskShape,
      shape: this.maskShape,
      points: this.points,
      x: event.x,
      y: event.y,
    });
  }

  // 创建 mask
  private createMask() {
    const view = this.context.view;
    const maskAttrs = this.getMaskAttrs();
    const maskShape = view.foregroundGroup.addShape({
      type: this.shapeType,
      name: 'mask',
      draggable: true,
      attrs: {
        fill: '#C5D4EB',
        opacity: 0.3,
        ...maskAttrs,
      },
    });
    return maskShape;
  }

  protected abstract getMaskAttrs(): LooseObject;

  // 生成 mask 的路径
  protected getMaskPath() {
    return [];
  }

  /**
   * 显示
   */
  public show() {
    if (this.maskShape) {
      this.maskShape.show();
      this.emitEvent('show');
    }
  }

  /**
   * 开始
   */
  public start(arg?: { maskStyle: LooseObject }) {
    this.starting = true;
    // 开始时，保证移动结束
    this.moving = false;
    this.points = [this.getCurrentPoint()];
    if (!this.maskShape) {
      this.maskShape = this.createMask();
      // 开始时设置 capture: false，可以避免创建、resize 时触发事件
      this.maskShape.set('capture', false);
    }
    this.updateMask(arg?.maskStyle);
    this.emitEvent('start');
  }

  /**
   * 开始移动
   */
  public moveStart() {
    this.moving = true;
    this.preMovePoint = this.getCurrentPoint();
  }
  /**
   * 移动 mask
   */
  public move() {
    if (!this.moving || !this.maskShape) {
      return;
    }
    const currentPoint = this.getCurrentPoint();
    const preMovePoint = this.preMovePoint;
    const dx = currentPoint.x - preMovePoint.x;
    const dy = currentPoint.y - preMovePoint.y;
    const points = this.points;
    each(points, (point) => {
      point.x += dx;
      point.y += dy;
    });
    this.updateMask();
    this.emitEvent('change');
    this.preMovePoint = currentPoint;
  }

  protected updateMask(maskStyle?: LooseObject) {
    const attrs = deepMix({}, this.getMaskAttrs(), maskStyle);
    this.maskShape.attr(attrs);
  }

  /**
   * 结束移动
   */
  public moveEnd() {
    this.moving = false;
    this.preMovePoint = null;
  }

  /**
   * 结束
   */
  public end() {
    this.starting = false;
    this.emitEvent('end');
    if (this.maskShape) {
      this.maskShape.set('capture', true);
    }
  }

  /**
   * 隐藏
   */
  public hide() {
    if (this.maskShape) {
      this.maskShape.hide();
      this.emitEvent('hide');
    }
  }

  /**
   * 大小变化
   */
  public resize() {
    // 只有进行中，才会允许大小变化
    if (this.starting && this.maskShape) {
      this.points.push(this.getCurrentPoint());
      this.updateMask();
      this.emitEvent('change');
    }
  }

  /**
   * 销毁
   */
  public destroy() {
    this.points = [];
    if (this.maskShape) {
      this.maskShape.remove();
    }
    this.maskShape = null;
    this.preMovePoint = null;
    super.destroy();
  }
}

export default MaskBase;
