import {Component, ElementRef, ViewChild, OnInit, Input, OnDestroy, HostListener} from '@angular/core';

import {
  Label,
  Sprite, tweenChange

} from './Unit';
import res from './resources';

import {Subject} from 'rxjs';
import {debounceTime} from 'rxjs/operators';

import TWEEN from '@tweenjs/tween.js';

export class MySpriteBase extends Sprite {

  width = 0;
  height = 0;
  _anchorX = 0;
  _anchorY = 0;
  _offX = 0;
  _offY = 0;
  scaleX = 1;
  scaleY = 1;
  alpha = 1;
  rotation = 0;
  visible = true;

  children = [this];

  img;
  _z = 0;


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

    if (imgObj) {

      this.img = imgObj;

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



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

  }



  update($event = null) {

    if (!this.visible) { return; }

    this.draw();
  }
  draw() {

    this.ctx.save();

    this.drawImage();
    // this.drawOther();

    this.ctx.restore();
  }

  drawImage() {


    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.updateChildren();


    // 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.img) {
          this.ctx.drawImage(this.img, this._offX, this._offY);
        }
      } else {

        this.children[i].update();

      }
    }
  }



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

    this.children.sort((a, b) => {

      // if (a === this) {
      //   return b._z;
      // } else if (b === this) {
      //   return a._z;
      // }
      return a._z - b._z;
    });

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

  set scale(value) {
    this.scaleX = this.scaleY = value;
  }
  get scale() {
    return this.scaleX;
  }
  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;
  }


  getBoundingBox() {

    const x = this.x + this._offX * this.scaleX;
    const y = this.y + this._offY * this.scaleY;
    const width = this.width * this.scaleX;
    const height = this.height * this.scaleY;

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

  // drawOther() {}
}



export class Diamond extends MySpriteBase {

  text = '';
  selected = true;
  showText = false;

  setData(data, showText = true) {
    this.text = data.value;
    this.selected = data.selected;

    this.showText = showText;

  }

  drawText() {

    if (!this.showText) {
      return;
    }

    this.ctx.font = '32px RoundedBold';
    this.ctx.textAlign = 'center';
    this.ctx.textBaseline = 'middle';
    this.ctx.fontWeight = 900;
    this.ctx.strokeStyle = '#000000';
    this.ctx.fillStyle = '#ffffff';
    this.ctx.lineWidth = '5';

    this.ctx.strokeText(this.text, 0, 0);
    this.ctx.fillText(this.text, 0, 0);
  }


  drawImage() {
    super.drawImage();

    this.drawText();
  }

  // drawOther() {
  //   this.drawText();
  // }
}

export class Lemon extends MySpriteBase {

  text;

  constructor(ctx, text) {
    super(ctx);
    this.text = text;
  }

  init(imgObj, anchorX: number = 0.5, anchorY: number = 0.5) {
    super.init(imgObj, anchorX, anchorY);

  }

  drawText() {
    //
    this.ctx.font = '25px RoundedBold';
    this.ctx.textAlign = 'center';
    this.ctx.textBaseline = 'middle';
    this.ctx.fontWeight = 900;
    this.ctx.strokeStyle = '#ffffff';
    this.ctx.lineWidth = '10';





    const chr = this.text.split('');
    let temp = '';
    const row = [];
    const w = this.width - 80;
    const disH = 30;



    for (let a = 0; a < chr.length; a++) {
      if (this.ctx.measureText(temp).width < w && this.ctx.measureText(temp + (chr[a])).width <= w) {
        temp += chr[a];
      } else {
        row.push(temp);
        temp = chr[a];
      }
    }
    row.push(temp);

    const x = 0;
    const y = -row.length * disH / 2 - 10;
    for (let b = 0 ; b < row.length; b++) {
      this.ctx.strokeText(row[b], x, y + ( b + 1 ) * disH ); // 每行字体y坐标间隔20
    }


    this.ctx.fillStyle = '#8b572a';
    for (let b = 0 ; b < row.length; b++) {
      this.ctx.fillText(row[b], x, y + ( b + 1 ) * disH ); // 每行字体y坐标间隔20
    }

  }

  drawImage() {
    super.drawImage();

    this.drawText();
  }



  hideItem(callBack, t: number = 0.8) {

    // console.log(' in hideItem ', this.alpha);
    const tween = new TWEEN.Tween(this)
      .to({ alpha: 0 }, t * 1000)
      // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
      .onComplete(function() {
        if (callBack) {
          callBack();
        }
      })
      .start(); // Start the tween immediately.


    // console.log('tween: ', tween);
  }

}




export class Item extends MySpriteBase {



  hideItem(callBack = null, t = 0.8) {

    const tween = new TWEEN.Tween(this)
      .to({ alpha: 0 }, t * 1000)
      // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
      .onComplete(function() {
        if (callBack) {
          callBack();
        }
      })
      .start(); // Start the tween immediately.
  }

  showItem(callBack = null, t = 0.8) {
    const tween = new TWEEN.Tween(this)
      .to({ alpha: 1 }, t * 1000)
      // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
      .onComplete(function() {
        if (callBack) {
          callBack();
        }
      })
      .start(); // Start the tween immediately.
  }



}




@Component({
  selector: 'app-play',
  templateUrl: './play.component.html',
  styleUrls: ['./play.component.css']
})
export class PlayComponent implements OnInit, OnDestroy {
  saveKey = 'ww_diamond';
  // 数据
  targets = [];
  colors = [];
  data;



  @ViewChild('canvas', {static: true}) canvas: ElementRef;
  @ViewChild('wrap', {static: true}) wrap: ElementRef;
  canvasWidth = 1280;
  canvasHeight = 576;

  canvasBaseW = 1280;
  canvasBaseH = 576;

  ctx;
  fps = 0;
  // lastFrameTime = 0;
  frametime = 0;  // 上一帧动画的时间，   两帧时间差


  mx;
  my; // 点击坐标


  // 资源
  rawImages = new Map(res);

  // 声音

  bgAudio = new Audio();
  successAudio = new Audio();
  finishAudio = new Audio();
  wrongAudio = new Audio();



  images = new Map();

  animationId: any;
  winResizeEventStream = new Subject();


  audioObj = {};
  mapScale = 1;


  canvasLeft;
  canvasTop;
  pcFlag = true;


  renderArr;

  downFlag = false;
  moveFlag = false;


  DIAMOND_LEN = 110;

  posArr = [
    [299, 506],
    [554, 430],
    [681, 433],
    [765, 507],
    [154, 499],
    [521, 522]
  ];


  gameEndFlag = false;
  options;

  picFlag = true;
  startPx;
  startPy;
  audioPlaying = false;


  diamondColorArr = ['d-red', 'd-yellow', 'd-purple'];
  slate;
  diamondArr = [];
  wordsArr = [];
  curDiamond;
  selectOptions;
  optionsArr = [];
  clickedDiamondFlag = false;
  endSpr;

  @HostListener('window:resize', ['$event'])
  onResize(event) {
    this.winResizeEventStream.next();
  }


  ngOnInit() {
    this.data = {
      contentObj: {
        wordnum: [{
          words: [{
            value: 'a',
            selected: false
          }, {
            value: 'p',
            selected: true
          }, {
            value: 'p',
            selected: false
          }, {
            value: 'l',
            selected: false
          }, {
            value: 'e',
            selected: false
          }, {
            value: '',
            selected: false
          }, {
            value: '',
            selected: false
          }, {
            value: '',
            selected: false
          }, {
            value: '',
            selected: false
          }, {
            value: '',
            selected: false
          }, {
            value: '',
            selected: false
          }, {
            value: '',
            selected: false
          }, {
            value: '',
            selected: false
          }, {
            value: '',
            selected: false
          }, {
            value: '',
            selected: false
          }],
          spelling_audio: '',
          pic_id: ''
        }],
        selectedArr: [{
          value: 'p',
          audio: '',
          index: 1
        }],
        audio_word: null,
        options: [{
          value: 'b',
          audio: ''
        }, {
          value: 'q',
          audio: ''
        }],
        pic_res_id: 'http://staging-teach.cdn.ireadabc.com/3362dd9e86df013ef4ac62739e5bdfee.jpg'
      }
    };

    // 获取数据
    const getData = (window as any).courseware.getData;
    getData((data) => {

      if (data && typeof data === 'object') {
        this.data = data;
      }
      // console.log('data:' , data);
      this.initAudio();
      this.initImg();
      this.initListener();
      if (window["air"]) {
        window["air"].hideAirClassLoading(this.saveKey, this.data);
      }
    }, this.saveKey);






  }

  ngOnDestroy() {
    window.cancelAnimationFrame(this.animationId);
    this.bgAudio.pause();
  }

  initData() {

    this.canvasWidth = this.wrap.nativeElement.clientWidth;
    this.canvasHeight = this.wrap.nativeElement.clientHeight;

    this.mapScale = this.canvasHeight / this.canvasBaseH;

    // this.itemLen = this.itemLenBase * this.mapScale;


    this.renderArr = [];
    this.gameEndFlag = false;
    this.endSpr = null;

    // console.log('this.data:', this.data);

    this.selectOptions = [];
    if (this.data.contentObj) {

      const options = this.data.contentObj.options;
      if (options) {
        // tslint:disable-next-line:prefer-for-of
        for (let i = 0; i < options.length; i++) {
          // options[i].selected = false;
          if (options[i].value) {
            this.selectOptions.push(options[i]);
          }
        }
      }

      const selectedArr = this.data.contentObj.selectedArr;
      if (selectedArr) {
        // tslint:disable-next-line:prefer-for-of
        for (let i = 0; i < selectedArr.length; i++) {
          // selectedArr[i].selected = true;
          this.selectOptions.push(selectedArr[i]);
        }
      }
    }

    if (this.data.contentObj.wordnum && this.data.contentObj.wordnum[0]) {

      const words = this.data.contentObj.wordnum[0].words;
      if (words) {

        this.wordsArr = [];

        // tslint:disable-next-line:prefer-for-of
        for (let i = 0; i < words.length; i++) {
          if (words[i].value) {
            this.wordsArr.push(words[i]);
          }
        }
      }

    }



  }

  IsPC() {

    if (document.body.ontouchstart !== undefined) {
      return false;
    } else {
      return true;
    }


  }




  initAudio() {

    const contentObj = this.data.contentObj;
    if (!contentObj) { return; }

    let options = [];
    if (this.data.contentObj && this.data.contentObj.options) {
      options = this.data.contentObj.options;
    }

    let selectedArr = [];
    if (this.data.contentObj && this.data.contentObj.selectedArr) {
      selectedArr = this.data.contentObj.selectedArr;
    }

    const arr = options.concat(selectedArr);
    // tslint:disable-next-line:prefer-for-of
    for (let i = 0; i <= arr.length; i++) {

      if (arr[i]) {

        const url = arr[i].audio;
        if (url) {

          const audio = new Audio();
          audio.src = url;
          // audio.src = contentObj[url];
          audio.load();
          this.audioObj[url] = audio;
        }
      }
    }

    const audioWordUrl = this.data.contentObj.audio_word;
    if (audioWordUrl) {
      const audio = new Audio();
      audio.src = audioWordUrl;
      audio.load();
      this.audioObj[audioWordUrl] = audio;
    }




    this.bgAudio.src = 'assets/diamond/music/bg.mp3';
    this.bgAudio.load();
    this.bgAudio.loop = true;
    this.bgAudio.volume = 0.6;

    this.finishAudio.src = 'assets/diamond/music/finish.mp3';
    this.finishAudio.load();



    this.wrongAudio.src = 'assets/diamond/music/wrong.mp3';
    this.wrongAudio.load();

    this.successAudio.src = 'assets/diamond/music/success.mp3';
    this.successAudio.load();

  }

  initImg() {
    const contentObj = this.data.contentObj;
    if (!contentObj) { return; }

    const url = 'pic_res_id';
    if (contentObj[url]) {

      // console.log('contentObj[url]:', contentObj[url]);
      this.picFlag = true;
      this.rawImages.set(url,  contentObj[url]);
    } else {
      this.picFlag = false;
    }






    // 预加载资源

    this.loadResources().then(() => {
      this.init();
      // this.lastFrameTime = Date.now();
      this.igniteLoop();
    });

  }








  init() {

    this.initData();
    this.initCtx();


    this.initItem();

  }

  initCtx() {

    this.ctx = this.canvas.nativeElement.getContext('2d');
    this.canvas.nativeElement.width = this.canvasWidth;
    this.canvas.nativeElement.height = this.canvasHeight;

  }


  initItem() {


    const paper = new MySpriteBase(this.ctx);
    paper.init(this.images.get('paper'));
    this.renderArr.push(paper);
    paper.scale = this.mapScale * 0.8;
    paper.x = this.canvasWidth / 2;
    paper.y = 170 * this.mapScale;

    if (this.picFlag) {
      const pic = new MySpriteBase(this.ctx);
      pic.init(this.images.get('pic_res_id'));
      paper.addChild(pic);

      pic.x = 2;
      pic.scaleX = paper.width * 0.32 / pic.width;
      pic.scaleY = paper.width * 0.32 / pic.height;
    }


    const slate = new MySpriteBase(this.ctx);
    slate.init(this.images.get('slate'));
    this.renderArr.push(slate);
    slate.x = paper.x;
    slate.y = 350 * this.mapScale;
    this.slate = slate;



    this.initDiamond();
    this.initSelectOptions();

  }

  initDiamond() {

    let curColor;

    // let colorIndex = 1;

    const len =  this.DIAMOND_LEN ;
    // window.innerWidth *  this.DIAMOND_LEN / 1280; //
    const diamondW = 115;
    const lehH = 49;
    const words = this.wordsArr;
    const offX = -(words.length * len / 2 - len / 2) * this.mapScale + this.canvasWidth / 2;

    // console.log('offX:', offX);

    const arr = [];
    // tslint:disable-next-line:prefer-for-of
    for (let i = 0; i < words.length; i++) {

      curColor = this.getDiamondColor(curColor);

      const diamond = new Diamond(this.ctx);
      if (words[i].selected) {
        diamond.init(this.images.get('question'));
        diamond.setData(words[i], false);
        this.addQuestionLight(diamond);

      } else {
        diamond.init(this.images.get(curColor));
        diamond.setData(words[i]);

      }

      arr.push(diamond);
      diamond.scale = len / diamondW * this.mapScale;
      diamond.x = offX + i * len * this.mapScale;
      console.log('diamond.x', diamond.x);
      diamond.y = this.slate.y - (lehH / 2) * this.mapScale;
      // @ts-ignore
      diamond.baseX = diamond.x;
      // @ts-ignore
      diamond.baseY = diamond.y;
      // @ts-ignore
      diamond.audio = this.audioObj[this.data.contentObj.audio_word];
    }

    this.diamondArr = arr;


  }

  addQuestionLight(diamond) {

    const qLight = new MySpriteBase(this.ctx);
    qLight.init(this.images.get('question_light'));
    diamond.addChild(qLight);

    qLight.visible = false;
    diamond.qLight = qLight;

  }

  getDiamondColor(curColor) {
    const colorArr = this.diamondColorArr;

    const tmpArr = colorArr.concat();
    if (curColor) {
      const oldIndex = tmpArr.indexOf(curColor);
      tmpArr.splice(oldIndex, 1);
    }
    const index = Math.floor( Math.random() * tmpArr.length );
    return tmpArr[index];
  }

  initSelectOptions() {


    let arr = this.selectOptions;

    const tmpOptions = arr.concat();
    const newArr = [];
    while (tmpOptions.length > 0) {
      const randomIndex = Math.floor(Math.random() * tmpOptions.length);
      newArr.push(tmpOptions[randomIndex]);
      tmpOptions.splice(randomIndex, 1);
    }
    arr = newArr;

    let curColor;
    this.optionsArr = [];
    // tslint:disable-next-line:prefer-for-of
    for (let i = 0; i < arr.length; i++) {

      curColor = this.getDiamondColor(curColor);

      if (this.posArr[i]) {

        const diamond = new Diamond(this.ctx);
        diamond.init(this.images.get(curColor));
        diamond.setData(arr[i]);

        this.optionsArr.push(diamond);
        const dl = this.DIAMOND_LEN ;
        // window.innerWidth *  this.DIAMOND_LEN / 1280; // this.DIAMOND_LEN
        diamond.scale =  dl / diamond.width * this.mapScale;
        diamond.x = this.posArr[i][0] * this.mapScale;
        diamond.y = this.posArr[i][1] * this.mapScale;
        // @ts-ignore
        diamond.baseX = diamond.x;
        // @ts-ignore
        diamond.baseY = diamond.y;

        this.addDiamondLight(diamond);

        if (arr[i].audio) {
          // @ts-ignore
          diamond.audio = this.audioObj[arr[i].audio];
        }
      }

    }



  }

  addDiamondLight(diamond) {

    const light = new MySpriteBase(this.ctx);
    light.init(this.images.get('light'));
    diamond.addChild(light, -2);

    light.visible = false;
    diamond.light = light;
  }



  checkTouchDiamond() {
    // tslint:disable-next-line:prefer-for-of
    for (let i = 0; i < this.diamondArr.length; i++) {

      // if (!this.diamondArr[i].selected) {
      if (this.checkClickTarget(this.diamondArr[i])) {
        this.clickedDiamondFlag = true;
        return this.diamondArr[i];
      }
      // }

    }
    // tslint:disable-next-line:prefer-for-of
    for (let i = 0; i < this.optionsArr.length; i++) {

      if (this.checkClickTarget(this.optionsArr[i])) {
        this.clickedDiamondFlag = false;
        return this.optionsArr[i];
      }
    }


    return null;
  }



  checkClickTarget(target) {

    const rect = target.getBoundingBox();
    if (this.checkPointInRect(this.mx, this.my, rect)) {
      return true;
    }

    return false;
  }



  hideAllLight() {

    // tslint:disable-next-line:prefer-for-of
    for (let i = 0; i < this.diamondArr.length; i ++) {
      if (this.diamondArr[i].qLight) {
        this.diamondArr[i].qLight.visible = false;
      }
    }

    // tslint:disable-next-line:prefer-for-of
    for (let i = 0; i < this.optionsArr.length; i ++) {
      if (this.optionsArr[i].light) {
        this.optionsArr[i].light.visible = false;
      }
    }
  }






  mapDown(event) {

    // console.log(' in mapDown:', event);
    if (this.gameEndFlag) { return; }

    this.downFlag = true;

    // this.curDiamond = this.checkTouchDiamond();

    this.startPx = this.mx;
    this.startPy = this.my;




    // --




    if (this.curDiamond) {
      for (let i = 0; i < this.diamondArr.length; i++) {

        if (this.diamondArr[i].qLight && !this.diamondArr[i].putEnd) {

          if (this.checkClickTarget(this.diamondArr[i])) {

            if ( this.diamondArr[i].text === this.curDiamond.text ) {

              this.hideAllLight();

              this.putSuccess(this.diamondArr[i]);


            } else {

              this.wrongAudio.play();
            }

            return;

            // if (this.checkPutSuccess()) {
            //   return;
            // }
          }
        }

      }
    }

    this.hideAllLight();


    this.curDiamond = this.checkTouchDiamond();

    if (this.curDiamond) {
      this.clickDiamond();
    }

    // --

    //
    // if (!this.audioPlaying) {
    //   this.audioPlaying = true;
    //   this.bgAudio.play();
    // }
  }

  mapMove(event) {
    //
    // if (!this.downFlag) { return; }
    // if (!this.curDiamond) { return; }
    //
    // // console.log(' in mapMove');
    //
    // const len = this.getPosDistance(this.mx, this.my, this.startPx, this.startPy);
    // if (!this.moveFlag && len >= 5) {
    //   this.moveFlag = true;
    // }
    //
    //
    // if (this.moveFlag && !this.clickedDiamondFlag) {
    //   this.curDiamond.x = this.mx;
    //   this.curDiamond.y = this.my;
    // }

  }

  mapUp(event) {

    // if (this.curDiamond) {
    //
    //   if (this.moveFlag) {
    //
    //     if (!this.curDiamond.selected) {
    //       this.checkOnQuestionTarget();
    //     }
    //   } else {
    //
    //     this.clickDiamond();
    //   }
    //   // console.log('x: ', this.curDiamond.x / this.mapScale);
    //   // console.log('y: ', this.curDiamond.y / this.mapScale);
    // }

    this.downFlag = false;
    this.moveFlag = false;
    // this.curDiamond = null;

  }

  clickDiamond() {
    if (this.curDiamond.audio) {
      this.curDiamond.audio.play();
    }


    if (this.curDiamond.light) {
      this.curDiamond.light.visible = true;
      this.showQuestionLight();
    }
  }

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

      if (this.diamondArr[i].qLight && !this.diamondArr[i].putEnd) {
        this.diamondArr[i].qLight.visible = true;
      }
    }
  }


  checkOnQuestionTarget() {

    let checkSuccess = false;
    for (let i = 0; i < this.diamondArr.length; i++) {

      if (this.diamondArr[i].selected && !this.diamondArr[i].putEnd) {


        if (this.checkRectInRect(this.diamondArr[i].getBoundingBox(), this.curDiamond.getBoundingBox())) {

          checkSuccess = true;
          if ( this.diamondArr[i].text === this.curDiamond.text ) {


            this.putSuccess(this.diamondArr[i]);
            return;
          }
        }

      }


    }

    if ( checkSuccess ) {
      this.checkPutFail();
    } else {
      this.backBasePos();
    }

  }



  backBasePos() {
    this.curDiamond.x = this.curDiamond.baseX;
    this.curDiamond.y = this.curDiamond.baseY;
  }


  checkPutFail() {
    this.wrongAudio.play();
    this.backBasePos();
  }

  putSuccess(target) {


    this.successAudio.play();

    this.curDiamond.x = target.x;
    this.curDiamond.y = target.y;


    const index = this.optionsArr.indexOf(this.curDiamond);
    this.optionsArr.splice(index, 1);


    this.diamondArr.push(this.curDiamond);
    this.curDiamond.audio = this.diamondArr[0].audio;

    this.curDiamond.putEnd = true;
    target.putEnd = true;


    this.checkGameEnd();
  }


  checkGameEnd() {

    const arr = this.diamondArr;
    for (let i = 0; i < arr.length; i++) {
      if (arr[i].selected && !arr[i].putEnd) {
        return false;
      }
    }

    this.gameEnd();


  }

  gameEnd() {

    this.finishAudio.play();

    // const endSpr = new EndSpr(this.ctx);
    // endSpr.init(this.images.get('end'));
    // endSpr.x = this.canvasWidth / 2;
    // endSpr.y = this.canvasHeight / 2;
    // this.endSpr = endSpr;
    //
    // endSpr.show2(this.mapScale);

    this.gameEndFlag = true;

  }





  igniteLoop() {

    this.fps = Math.round(1000 / this.frametime);
    this.animationId = window.requestAnimationFrame(this.igniteLoop.bind(this));
    // 清除画布内容
    this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);


    for (let i = 0; i < this.renderArr.length; i++) {
      this.renderArr[i].update(this);
    }

    for (let i = 0; i < this.diamondArr.length; i++) {
      this.diamondArr[i].update(this);
    }

    for (let i = 0; i < this.optionsArr.length; i++) {
      this.optionsArr[i].update(this);
    }

    if (this.endSpr) {
      this.endSpr.update(this);
    }


    TWEEN.update();
  }








  initListener() {

    this.winResizeEventStream
      .pipe(debounceTime(500))
      .subscribe(data => {
        this.renderAfterResize();
      });


    // this.pcFlag = this.IsPC();


    // if (this.pcFlag) {

    this.canvas.nativeElement.addEventListener('mousedown', (event) => {

      // console.log('mousedown ');
      setMxMyByMouse(event);
      this.mapDown(event);
    });

    this.canvas.nativeElement.addEventListener('mousemove', (event) => {

      // console.log('mousemove ');
      setMxMyByMouse(event);
      this.mapMove(event);
    });

    this.canvas.nativeElement.addEventListener('mouseup', (event) => {

      // console.log('mouseup ');
      setMxMyByMouse(event);
      this.mapUp(event);
    });


    const setMxMyByMouse = (event) => {

      // console.log(' in setMxMyByMouse', event);
      this.mx = event.offsetX;
      this.my = event.offsetY;
    };



    // } else {

    this.canvas.nativeElement.addEventListener('touchstart', (event) => {

      // console.log('touchstart ');
      setMxMyByTouch(event);
      this.mapDown(event);
    });

    this.canvas.nativeElement.addEventListener('touchmove', (event) => {

      // console.log('touchmove ');
      setMxMyByTouch(event);
      this.mapMove(event);
    });

    this.canvas.nativeElement.addEventListener('touchend', (event) => {

      // console.log('touchend ');
      setMxMyByTouch(event);
      this.mapUp(event);
    });

    this.canvas.nativeElement.addEventListener('touchcancel', (event) => {

      // console.log('touchcancel ');
      setMxMyByTouch(event);
      this.mapUp(event);
    });


    const setMxMyByTouch = (event) => {

      // console.log('in setMxMyByTouch', event);
      if (event.touches.length <= 0) {
        return;
      }

      if (this.canvasLeft == null) {
        setParentOffset();
      }

      this.mx = event.touches[0].pageX - this.canvasLeft;
      this.my = event.touches[0].pageY - this.canvasTop;
    };


    const setParentOffset = () => {

      const rect = this.canvas.nativeElement.getBoundingClientRect();
      this.canvasLeft = rect.left;
      this.canvasTop = rect.top;
    };
    // }





  }


  loadResources() {
    const pr = [];
    this.rawImages.forEach((value, key) => {// 预加载图片

      // console.log('value:', value);
      // console.log('key:', key);
      const p = this.preload(value)
        // const p = this.preload( `/api/media-resource/${value}/file`)
        .then(img => this.images.set(key, img))
        .catch(err => console.log(err));
      pr.push(p);
    });
    return Promise.all(pr);
  }

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


  renderAfterResize() {
    this.canvasWidth = this.wrap.nativeElement.clientWidth;
    this.canvasHeight = this.wrap.nativeElement.clientHeight;
    this.init();
  }


  checkPointInRect(x, y, rect) {
    if (x >= rect.x && x <= rect.x + rect.width) {
      if (y >= rect.y && y <= rect.y + rect.height) {
        return true;
      }
    }
    return false;
  }

  checkRectInRect(rect1, rect2) {

    return !(rect1.x + rect1.width < rect2.x || rect1.y + rect1.height < rect2.y
      || rect2.x + rect2.width < rect1.x || rect2.y + rect2.height < rect1.y);

  }

  getPosByAngle(angle, len) {

    const radian = angle * Math.PI / 180;
    const x = Math.sin(radian) * len;
    const y = Math.cos(radian) * len;

    return {x, y};

  }

  getPosDistance(sx, sy, ex, ey) {

    const _x = ex - sx;
    const _y = ey - sy;
    const len = Math.sqrt( Math.pow(_x, 2) + Math.pow(_y, 2) );
    return len;
  }



}
