/*
 * *********************************************************************************************************************
 *
 *          !!
 *        .F88X
 *        X8888Y
 *      .}888888N;
 *        i888888N;        .:!              .I$WI:
 *          R888888I      .'N88~            i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
 *          .R888888I    .;N8888~          .X8'  "8I.!,/8"  !%NY8`"8I8~~8>,88I
 *            +888888N;  .8888888Y                                  "&&8Y.}8,
 *            ./888888N;  .R888888Y        .'}~    .>}'.`+>  i}!    "i'  +/'  .'i~  !11,.:">,  .~]!  .i}i
 *              ~888888%:  .I888888l      .]88~`1/iY88Ii+1'.R$8$8]"888888888>  Y8$  W8E  X8E  W8888'188Il}Y88$*
 *              18888888    E8888881    .]W%8$`R8X'&8%++N8i,8N%N8+l8%`  .}8N:.R$RE%N88N%N$K$R  188,FE$8%~Y88I
 *            .E888888I  .i8888888'      .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
 *            8888888I  .,N888888~        ~88i"8W,!N8*.I88.}888%F,i$88"F88"  888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
 *          i888888N'      I888Y          ]88;/EX*IFKFK88X  K8R  .l8W  88Y  ~88}'88E&%8W.X8N``]88!.$8K  .:W8I
 *        .i888888N;        I8Y          .&8$  .X88!  i881.:%888>I88  ;88]  +88+.';;;;:.Y88X  18N.,88l  .+88/
 *      .:R888888I
 *      .&888888I                                          Copyright (c) 2016-2020.  博锐尚格科技股份有限公司
 *        ~8888'
 *        .!88~                                                                     All rights reserved.
 *
 * *********************************************************************************************************************
 */
import { SColor, SPainter, SPoint, SRect } from "@persagy-web/draw";
import { SMouseButton, SMouseEvent, SUndoStack } from "@persagy-web/base";
import { SItemStatus } from "@persagy-web/big";;
import {
  SLineStyle,
  SGraphItem, SGraphPointListInsert
} from "@persagy-web/graph/";
import { SGraphEdit } from "..";

/**
 * 折线编辑类
 *
 * @author  haojianlong
 */
export class STriangleEdit extends SGraphEdit {
  /** 是否绘制完成  */
  _status: SItemStatus = SItemStatus.Normal;
  get status(): SItemStatus {
    return this._status;
  }
  set status(v: SItemStatus) {
    this._status = v;
    this.undoStack.clear();
    this.update();
  }
  /** 矩形两个对角 */
  private _line: SPoint[] = [];
  get line(): SPoint[] {
    return this._line;
  } // Get line
  set line(arr: SPoint[]) {
    this._line = arr;
    this.update();
  } // Get line
  // 矩形左上角
  private _leftTop: SPoint = new SPoint();
  // 矩形右下角
  private _rightBottom: SPoint = new SPoint();
  // 绘制三角形的点数组
  private pointList: SPoint[] = [];
  /** 线条颜色    */
  _strokeColor: SColor = SColor.Black;
  get strokeColor(): SColor {
    return this._strokeColor;
  }
  set strokeColor(v: SColor) {
    this._strokeColor = v;
    this.update();
  }
  /** 填充色 */
  _fillColor: SColor = new SColor("#2196f3");
  get fillColor(): SColor {
    return this._fillColor;
  }
  set fillColor(v: SColor) {
    this._fillColor = v;
    this.update();
  }
  /** 边框样式 */
  _lineStyle: SLineStyle = SLineStyle.Solid;
  get lineStyle(): SLineStyle {
    return this._lineStyle;
  }
  set lineStyle(v: SLineStyle) {
    this._lineStyle = v;
    this.update();
  }
  /** 线条宽度    */
  _lineWidth: number = 1;
  get lineWidth(): number {
    return this._lineWidth;
  }
  set lineWidth(v: number) {
    this._lineWidth = v;
    this.update();
  }
  /** undo/redo堆栈 */
  private undoStack: SUndoStack = new SUndoStack();

  /**
   * 构造函数
   *
   * @param parent    指向父对象
   * @param data      矩形数据
   */
  constructor(parent: SGraphItem | null, l?: SPoint | SPoint[]) {
    super(parent);
    if (l) {
      if (l instanceof SPoint) {
        this.line.push(l);
        this._leftTop = l;
        this._rightBottom = l;
      } else {
        this.line = l;
        this.calRect()
      }
    } else {
      this.line = [];
    }
  } // Constructor

  /**
   * 大小改变
  */
  resize(oldSize: SRect, newSize: SRect): void {
    const xs = newSize.width / oldSize.width;
    const ys = newSize.height / oldSize.height;
    this.line = this.line.map(t => {
      t.x = t.x * xs;
      t.y = t.y * ys;
      return t
    })
    this.calRect()
    this.update()
  }

  /**
     * 鼠标按下事件
     *
     * @param   event   鼠标事件
     * @return  是否处理事件
     * */
  onMouseDown(event: SMouseEvent): boolean {
    if (event.buttons == SMouseButton.LeftButton) {
      if (this.status == SItemStatus.Create) {
        this.addPoint(new SPoint(event.x, event.y));
        return true;
      } else {
        return super.onMouseDown(event);
      }
    }
    return true;
  } // Function onMouseDown()

  /**
     * 鼠标移动事件
     *
     * @param   event   鼠标事件
     * @return  是否处理事件
     * */
  onMouseMove(event: SMouseEvent): boolean {
    if (this.status == SItemStatus.Create) {
      if (this.line[0] instanceof SPoint) {
        this.line[1] = new SPoint(event.x, event.y);
        this.calRect()
      }
    } else {
      return super.onMouseMove(event);
    }
    this.update();
    return true;
  } // Function onMouseMove()

  /**
     * 鼠标抬起事件
     *
     * @param	event         事件参数
     * @return	boolean
     */
  onMouseUp(event: SMouseEvent): boolean {
    if (this.status != SItemStatus.Create) {
      super.onMouseUp(event);
    }
    return true;
  } // Function onMouseUp()

  /**
   * 计算矩形的左上角和右下角
  */
  private calRect(): void {
    if (this.line.length > 1) {
      const fi = this.line[0];
      const se = this.line[1];
      let minx, maxx, miny, maxy;
      if (fi.x < se.x) {
        minx = fi.x;
        maxx = se.x;
      } else {
        minx = se.x;
        maxx = fi.x;
      }
      if (fi.y < se.y) {
        miny = fi.y;
        maxy = se.y;
      } else {
        miny = se.y;
        maxy = fi.y;
      }
      this._leftTop = new SPoint(minx, miny)
      this._rightBottom = new SPoint(maxx, maxy)
      this.calTriangel()
    }
  } // Function calRect

  /**
   * 计算绘制图形的3个点
  */
  private calTriangel(): void {
    this.pointList = [];
    this.pointList.push(new SPoint(this._leftTop.x, this._rightBottom.y))
    this.pointList.push(new SPoint((this._leftTop.x+this._rightBottom.x)/2, this._leftTop.y))
    this.pointList.push(new SPoint(this._rightBottom.x, this._rightBottom.y))
  } // Function calRect

  /**
     * 添加点至数组中
     *
     * @param   p       添加的点
     * */
  private addPoint(p: SPoint): void {
    if (this.line.length < 2) {
      this.line.push(p);
      this.recordAction(SGraphPointListInsert, [this.line, p]);
    } else {
      this.line[1] = p;
      this.recordAction(SGraphPointListInsert, [this.line, p, 1]);
      this.status = SItemStatus.Normal;
      this.releaseItem();
      this.$emit("finishCreated");
    }
    this.calRect()
    this.update();
  } // Function addPoint()

  /**
     * 记录相关动作并推入栈中
     *
     * @param	SGraphCommand   相关命令类
     * @param	any             对应传入参数
     */
  protected recordAction(SGraphCommand: any, any: any[]): void {
    // 记录相关命令并推入堆栈中
    const command = new SGraphCommand(this.scene, this, ...any);
    this.undoStack.push(command);
  } // Function recordAction()

  /**
   * Item对象边界区域
   *
   * @return  SRect   外接矩阵
   * */
  boundingRect(): SRect {
    if (this.line.length > 1) {
      this.calRect()
      return new SRect(this._leftTop, this._rightBottom);
    }
    return new SRect()
  } // Function boundingRect()

  /**
   * 撤销操作
   *
   */
  undo(): void {
    if (this._status != SItemStatus.Normal) {
      this.undoStack.undo();
    }
  } // Function undo()

  /**
   * 重做操作
   *
   */
  redo(): void {
    if (this._status != SItemStatus.Normal) {
      this.undoStack.redo();
    }
  } // Function redo()

  /**
   * 取消操作执行
   *
   * */
  cancelOperate(): void {
    if (this.status == SItemStatus.Create) {
      this.parent = null;
      this.releaseItem();
    } else if (this.status == SItemStatus.Edit) {
      this.status = SItemStatus.Normal;
      this.releaseItem();
    }
  } // Function cancelOperate()

  /**
   * Item绘制操作
   *
   * @param   painter painter对象
   */
  onDraw(painter: SPainter): void {
    if (this.line.length == 2) {
      painter.pen.color = this.strokeColor;
      painter.brush.color = this.fillColor;
      painter.pen.lineWidth = this.lineWidth;
      if (this.lineStyle == SLineStyle.Dashed) {
        painter.pen.lineDash = [
            painter.toPx(this.lineWidth * 3),
            painter.toPx(this.lineWidth * 7)
        ];
      } else if (this.lineStyle == SLineStyle.Dotted) {
          painter.pen.lineDash = [
              painter.toPx(this.lineWidth * 2),
              painter.toPx(this.lineWidth * 2)
          ];
      }
      painter.drawPolygon(this.pointList);
    }
  } // Function onDraw()
} // Class STriangleEdit