class MySprite {


  x = 0;
  y = 0;
  radius = 0;
  margin = 0;
  ctx;
  
  
  _width = 0;
  _height = 0;
  _anchorX = 0;
  _anchorY = 0;
  _offX = 0;
  _offY = 0;
  scaleX = 1;
  scaleY = 1;
  _alpha = 1;
  rotation = 0;
  visible = true;
  skewX = 0;
  skewY = 0;

  _shadowFlag = false;
  _shadowColor;
  _shadowOffsetX = 0;
  _shadowOffsetY = 0;
  _shadowBlur = 5;

  _radius = 0;

  children = [this];

  childDepandVisible = true;
  childDepandAlpha = false;

  img;
  _z = 0;






  constructor(ctx = null) {
    if (!ctx) {
      this.ctx = window['curCtx'];
    } else {
      this.ctx = ctx;
    }
  }



  init(imgObj = null, anchorX = 0.5, anchorY = 0.5) {

    if (imgObj) {

      this.img = imgObj;

      this.width = this.img.width;
      this.height = this.img.height;


    }

    this.anchorX = anchorX;
    this.anchorY = anchorY;
  }


  setShadow(offX, offY, blur, color = 'rgba(0, 0, 0, 0.3)') {


    this._shadowFlag = true;
    this._shadowColor = color;
    this._shadowOffsetX = offX;
    this._shadowOffsetY = offY;
    this._shadowBlur = blur;

  }

  setRadius(r) {
    this._radius = r;
  }


  update($event = null) {
    if (!this.visible && this.childDepandVisible) {
      return;
    }

    this.draw();

  }
  draw() {

    this.ctx.save();

    this.drawInit();

    this.updateChildren();

    this.ctx.restore();


  }

  drawInit() {

    this.ctx.translate(this.x, this.y);

    this.ctx.rotate(this.rotation * Math.PI / 180);

    this.ctx.scale(this.scaleX, this.scaleY);

    this.ctx.globalAlpha = this.alpha;

    this.ctx.transform(1, this.skewX, this.skewY, 1, 0, 0);





    if (this._radius) {

      const r = this._radius;
      const w = this.width;
      const h = this.height;

      this.ctx.lineTo(-w / 2, h / 2);          // 创建水平线
      this.ctx.arcTo(-w / 2, -h / 2, -w / 2 + r, -h / 2, r);
      this.ctx.arcTo(w / 2, -h / 2, w / 2, -h / 2 + r, r);
      this.ctx.arcTo(w / 2, h / 2, w / 2 - r, h / 2, r);
      this.ctx.arcTo(-w / 2, h / 2, -w / 2, h / 2 - r, r);

      this.ctx.clip();
    }

  }

  drawSelf() {



    if (this._shadowFlag) {
      this.ctx.shadowOffsetX = this._shadowOffsetX;
      this.ctx.shadowOffsetY = this._shadowOffsetY;
      this.ctx.shadowBlur = this._shadowBlur;
      this.ctx.shadowColor = this._shadowColor;
    } else {
      this.ctx.shadowOffsetX = 0;
      this.ctx.shadowOffsetY = 0;
      this.ctx.shadowBlur = null;
      this.ctx.shadowColor = null;
    }


    if (this.img) {
      this.ctx.drawImage(this.img, this._offX, this._offY);
    }


  }

  updateChildren() {

    if (this.children.length <= 0) { return; }

    for (let i = 0; i < this.children.length; i++) {

      if (this.children[i] === this) {

        if (this.visible) {
          this.drawSelf();
        }
      } else {

        this.children[i].update();
      }
    }
  }


  load(url, anchorX = 0.5, anchorY = 0.5) {

    return new Promise((resolve, reject) => {
      const img = new Image();
      img.onload = () => resolve(img);
      img.onerror = reject;
      img.src = url;
    }).then(img => {

      this.init(img, anchorX, anchorY);
      return img;
    });
  }

  addChild(child, z = 1) {
    if (this.children.indexOf(child) === -1) {
      this.children.push(child);
      child._z = z;
      child.parent = this;
    }

    this.children.sort((a, b) => {
      return a._z - b._z;
    });


    if (this.childDepandAlpha) {
      child.alpha = this.alpha;
    }

  }
  removeChild(child) {
    const index = this.children.indexOf(child);
    if (index !== -1) {
      this.children.splice(index, 1);
    }
  }

  removeChildren() {
    for (let i = 0; i < this.children.length; i++) {
      if (this.children[i]) {
        if (this.children[i] != this) {
          this.children.splice(i, 1);
          i --;
        }
      }
    }
  }

  _changeChildAlpha(alpha) {
    for (let i = 0; i < this.children.length; i++) {
      if (this.children[i] != this) {
        this.children[i].alpha = alpha;
      }
    }
  }

  set alpha(v) {
    this._alpha = v;
    if (this.childDepandAlpha) {
      this._changeChildAlpha(v);
    }
  }
  get alpha() {
    return this._alpha;
  }
  set width(v) {
    this._width = v;
    this.refreshAnchorOff();
  }
  get width() {
    return this._width;
  }
  set height(v) {
    this._height = v;
    this.refreshAnchorOff();
  }
  get height() {
    return this._height;
  }
  set anchorX(value) {
    this._anchorX = value;
    this.refreshAnchorOff();
  }
  get anchorX() {
    return this._anchorX;
  }
  set anchorY(value) {
    this._anchorY = value;
    this.refreshAnchorOff();
  }
  get anchorY() {
    return this._anchorY;
  }
  refreshAnchorOff() {
    this._offX = -this._width * this.anchorX;
    this._offY = -this._height * this.anchorY;
  }

  setScaleXY(value) {
    this.scaleX = this.scaleY = value;
  }

  getBoundingBox() {


    const getParentData = (item) => {

      let px = item.x;
      let py = item.y;

      let sx = item.scaleX;
      let sy = item.scaleY;
      const parent = item.parent;
      if (parent) {

        const obj = getParentData(parent);

        const _x = obj.px;
        const _y = obj.py;
        const _sx = obj.sx;
        const _sy = obj.sy;

        px = _x + item.x * _sx;
        py = _y + item.y * _sy;

        sx *= _sx;
        sy *= _sy;

      }

      return {px, py, sx, sy};
    };


    const data = getParentData(this);


    const x = data.px + this._offX * Math.abs(data.sx);
    const y = data.py + this._offY * Math.abs(data.sy);
    const width = this.width * Math.abs(data.sx);
    const height = this.height * Math.abs(data.sy);

    // const x = this.x + this._offX * Math.abs(this.scaleX);
    // const y = this.y + this._offY * Math.abs(this.scaleY);
    // const width = this.width * Math.abs(this.scaleX);
    // const height = this.height * Math.abs(this.scaleY);

    return {x, y, width, height};
  }

}