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

import {
  Label,
  MySprite, 
  tweenChange, 
  RichText, 
  randomSortByArr, 
  ShapeRect, 
  LineRect, 
  removeItemFromArr, 
  hideItem, 
  shake,
  moveItem,
  showPopParticle,
  showItem,
  rotateItem,
  ShapeCircle,

} from './Unit';
import {res, resAudio} from './resources';
import {Subject} from 'rxjs';
import {debounceTime, flatMap} from 'rxjs/operators';
import TWEEN from '@tweenjs/tween.js';

@Component({
  selector: 'app-play',
  templateUrl: './play.component.html',
  styleUrls: ['./play.component.scss']
})
export class PlayComponent implements OnInit, OnDestroy {

  /**
   * 数据
   */
  _data;
  soundID: number;
  wordList: any[];
  optionRectArrBak: any[];
  wordArrBg = [];
  wordBgList: any;

  @Input()
  set data(data) {
    this._data = data;
  }
  get data() {
    return this._data;
  }

  @Input()
  sid;

  @ViewChild('canvas', {static: true }) canvas: ElementRef;
  @ViewChild('wrap', {static: true }) wrap: ElementRef;

  downFlag;
  endPageArr: any[];
  endRectArr;
  optionRectArr;
  optionBgArr;
  curOptionTarget;
  curOptionRect;
  bg: any;
  hotZoneArr: any[];
  bgLayer: MySprite;
  gameEndFlag: boolean;
  curPageIndex: number;
  ctx;
  fps = 0;
  frametime = 0;  // 上一帧动画的时间，   两帧时间差
  canvasWidth = 1280; // canvas实际宽度
  canvasHeight = 720; // canvas实际高度
  canvasBaseW = 1280; // canvas 资源预设宽度
  canvasBaseH = 720;  // canvas 资源预设高度
  mx; // 点击x坐标
  my; // 点击y坐标
  rawImages = new Map(res);
  rawAudios = new Map(resAudio);
  images = new Map();
  animationId: any;
  winResizeEventStream = new Subject();
  audioObj = {};
  renderArr;
  mapScale = 1;
  canvasLeft;
  canvasTop;
  saveKey = 'test_0011';
  KEY = 'test_0011';
  // 将被删除的
  btnLeft;
  btnRight;
  pic1;
  pic2;
  canTouch = true;
  curPic;
  bgArr;
  wordArr;
  soundClose;
  soundOpen;
  showSoundFlag;
  audio;
  picArr;
  picIndex;
  curData;
  space = 200;
  audioPlayer = new Audio();
  audioRect = new Audio();
  audioWord = new Audio();
  audioClick = new Audio();
  audioFinish = new Audio();
  spotList = [];
  disW;
  particleLayer;
  showPetalFlag;
  itemW = 140;
  spotW = 70;
  itemH = 75;
  topRect;
  optionRect;
  ObjArr = [];
  typeA = [];
  typeB = [];
  typeC = [];
  question;

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

  ngOnInit() {
    /**
     * 获取数据
     */
    const getData = (<any> window).courseware.getData;
    getData((data) => {
      if (data && typeof data == 'object') {
        this.data = data;
      } else {
        this.data = {};
      }
      if (!this.data.contentObj) {
        this.data.contentObj = {};
      }
      // 初始化 各事件监听
      this.initListener();
      // 若无数据 则为预览模式 需要填充一些默认数据用来显示
      this.initDefaultData();
      // 初始化 音频资源
      this.initAudio();
      // 初始化 图片资源
      this.initImg();
      // 开始预加载资源
      this.load();
    }, this.saveKey);
  }

  ngOnDestroy() {
    window['curCtx'] = null;
    window.cancelAnimationFrame(this.animationId);
    this.gameEndFlag = true;
  }

  load() {
    /**
     * 预加载资源
     */
    this.loadResources().then(() => {
      window["air"].hideAirClassLoading(this.KEY, this.data);
      this.init();
      this.update();
    });
  }

  init() {
    this.initCtx();
    this.initData();
    this.initView();
  }

  initCtx() {
    this.ctx = this.canvas.nativeElement.getContext('2d');
    this.canvas.nativeElement.width = this.canvasWidth;
    this.canvas.nativeElement.height = this.canvasHeight;
    window['curCtx'] = this.ctx;
  }

  gameEnd() {
    this.showEndPatal();
    console.log('finish');
    const finishLink: any = this.rawAudios.get('finish');
    this.audioFinish.src = finishLink;
    this.audioFinish.load();
    this.audioFinish.play();
    this.playAudio('finish');
    setTimeout(( ) => {
      this.showPetalFlag = false;
    }, 5000);
  }

  updateItem(item) {
    if (item) {
      item.update();
    }
  }

  updateArr(arr) {
    if (!arr) {
      return;
    }
    for (let i = 0; i < arr.length; i++) {
      arr[i].update(this);
    }
  }

  initHotZone() {
    let curBgRect;
    if (this.bg) {
      curBgRect = this.bg.getBoundingBox();
    }
    let oldBgRect = this.data.contentObj.bgItem.rect;
    if (!oldBgRect) {
      oldBgRect = curBgRect;
    }
    const rate = curBgRect.width / oldBgRect.width;
    this.hotZoneArr = [];
    const arr = this.data.contentObj.hotZoneItemArr;
    if (!arr) return;
    for (let i = 0; i < arr.length; i++) {
      const data = JSON.parse(JSON.stringify(arr[i]));
      data.rect.x *= rate;
      data.rect.y *= rate;
      data.rect.width *= rate;
      data.rect.height *= rate;
      data.rect.x += curBgRect.x;
      data.rect.y += curBgRect.y;
      const hotZone = this.getHotZoneItem(data);
      hotZone.alpha = 0;
      this.hotZoneArr.push(hotZone);
    }
  }

  getHotZoneItem(data) {
    const saveRect = data.rect;
    const item = new ShapeRect(this.ctx);
    item.setSize(saveRect.width, saveRect.height);
    item.x = saveRect.x ;
    item.y = saveRect.y ;
    item['data'] = data;
    this.renderArr.push(item);
    return item;
  }

  showEndPatal() {
    this.endPageArr = [];
    this.showPetalFlag = true;
    this.addPetal();
  }

  stopEndPatal() {
    this.endPageArr = [];
    this.showPetalFlag = false;
  }

  addPetal() {
    if (!this.showPetalFlag) {
      return;
    }
    const petal = this.getPetal();
    this.endPageArr.push(petal);
    moveItem(petal, petal.x, this.canvasHeight + petal.height * petal.scaleY, petal['time'], () => {
      removeItemFromArr(this.endPageArr, petal);
    });
    rotateItem(petal, petal['tr'], petal['time']);
    setTimeout(() => {
      this.addPetal();
    }, 200);
  }

  getPetal() {
    const petal = new MySprite(this.ctx);
    const id = Math.ceil( Math.random() * 3 );
    petal.init(this.images.get('petal_' + id));
    const randomS = (Math.random() * 0.4 + 0.6) * this.mapScale;
    petal.setScaleXY(randomS);
    const randomR = Math.random() * 360;
    petal.rotation = randomR;
    const randomX = Math.random() * this.canvasWidth;
    petal.x = randomX;
    petal.y = -petal.height / 2 * petal.scaleY;
    const randomT = 2 + Math.random() * 5;
    petal['time'] = randomT;
    let randomTR = 360 * Math.random(); // - 180;
    if (Math.random() < 0.5) { randomTR *= -1; }
    petal['tr'] = randomTR;
    return petal;
  }

  initListener() {
    this.winResizeEventStream
      .pipe(debounceTime(500))
      .subscribe(data => {
        this.renderAfterResize();
      });
    const setParentOffset = () => {
      const rect = this.canvas.nativeElement.getBoundingClientRect();
      this.canvasLeft = rect.left;
      this.canvasTop = rect.top;
    };
    const 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 setMxMyByMouse = (event) => {
      this.mx = event.offsetX;
      this.my = event.offsetY;
    };
    let firstTouch = true;
    const touchDownFunc = (e) => {
      if (firstTouch) {
        firstTouch = false;
        removeMouseListener();
      }
      console.log('touch down');
      setMxMyByTouch(e);
      this.mapDown(e);
    };
    const touchMoveFunc = (e) => {
      setMxMyByTouch(e);
      this.mapMove(e);
    };
    const touchUpFunc = (e) => {
      setMxMyByTouch(e);
      this.mapUp(e);
    };
    const mouseDownFunc = (e) => {
      if (firstTouch) {
        firstTouch = false;
        removeTouchListener();
      }
      setMxMyByMouse(e);
      this.mapDown(e);
    };
    const mouseMoveFunc = (e) => {
      setMxMyByMouse(e);
      this.mapMove(e);
    };
    const mouseUpFunc = (e) => {
      setMxMyByMouse(e);
      this.mapUp(e);
    };
    const element = this.canvas.nativeElement;
    const addTouchListener = () => {
      element.addEventListener('touchstart', touchDownFunc);
      element.addEventListener('touchmove', touchMoveFunc);
      element.addEventListener('touchend', touchUpFunc);
      element.addEventListener('touchcancel', touchUpFunc);
    };
    const removeTouchListener = () => {
      element.removeEventListener('touchstart', touchDownFunc);
      element.removeEventListener('touchmove', touchMoveFunc);
      element.removeEventListener('touchend', touchUpFunc);
      element.removeEventListener('touchcancel', touchUpFunc);
    };
    const addMouseListener = () => {
      element.addEventListener('mousedown', mouseDownFunc);
      element.addEventListener('mousemove', mouseMoveFunc);
      element.addEventListener('mouseup', mouseUpFunc);
    };
    const removeMouseListener = () => {
      element.removeEventListener('mousedown', mouseDownFunc);
      element.removeEventListener('mousemove', mouseMoveFunc);
      element.removeEventListener('mouseup', mouseUpFunc);
    };
    addMouseListener();
    addTouchListener();
  }

  playAudio(key, now = false, callback = null) {
    const audio = this.audioObj[key];
    if (audio) {
      if (now) {
        audio.pause();
        audio.currentTime = 0;
      }
      if (callback) {
        audio.onended = () => {
          callback();
        };
      }
      audio.play();
    }
  }

  showArr(arr) {
    if (!arr) {
      return;
    }
    for (let i = 0; i < arr.length; i++) {
      arr[i].visible = true;
    }
  }
  
  hideArr(arr) {
    if (!arr) {
      return;
    }
    for (let i = 0; i < arr.length; i++) {
      arr[i].visible = false;
    }
  }

  IsPC() {
    if (window['ELECTRON']) {
      return false; // 封装客户端标记
    }
    if (document.body.ontouchmove !== undefined && document.body.ontouchmove !== undefined) {
      return false;
    } else {
      return true;
    }
  }

  loadResources() {
    const pr = [];
    this.rawImages.forEach((value, key) => {// 预加载图片
      const p = this.preload(value)
        .then(img => {
          this.images.set(key, img);
        })
        .catch(err => console.log(err));
      pr.push(p);
    });
    this.rawAudios.forEach((value, key) => {// 预加载音频
      const a = this.preloadAudio(value)
        .then(() => {
          // this.images.set(key, img);
        })
        .catch(err => console.log(err));
      pr.push(a);
    });
    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;
    });
  }

  preloadAudio(url) {
    return new Promise((resolve, reject) => {
      const audio = new Audio();
      audio.oncanplay = (a) => {
        resolve();
      };
      audio.onerror = () => {
        reject();
      };
      audio.src = url;
      audio.load();
    });
  }

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

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

  getWorlRect(target) {
    let rect = target.getBoundingBox();
    if (target.parent) {
      const pRect = this.getWorlRect(target.parent);
      rect.x += pRect.x;
      rect.y += pRect.y;
    }
    return rect;
  }

  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;
  }

  addUrlToAudioObj(key, url = null, vlomue = 1, loop = false, callback = null) {
    const audioObj = this.audioObj;
    if (url == null) {
      url = key;
    }
    this.rawAudios.set(key, url);
    const audio = new Audio();
    audio.src = url;
    audio.load();
    audio.loop = loop;
    audio.volume = vlomue;
    audioObj[key] = audio;
    if (callback) {
      audio.onended = () => {
        callback();
      };
    }
  }

  addUrlToImages(url) {
    this.rawImages.set(url, url);
  }

  // ======================================================编写区域==========================================================================

  /**
   * 添加默认数据 便于无数据时的展示
   */
  initDefaultData() {
    let contentObj = this.data.contentObj;
    let picArr = this.data.contentObj.picArr;
    if (!picArr || picArr.length == 0) {
      picArr = [{
        audio_url : 'assets/play/default/audio.mp3',
        pic_url: 'assets/play/default/pic.jpg',
        wordArr: [
          {text: 'one', id: '0'},
          {text: 'aaa', id: '1'},
          {text: 'three', id: '2'},
        ],
      }];
      this.data.contentObj.picArr = picArr;
      // this.initBaseBg();
      
    }
    console.log('picArr',picArr);
    console.log('contentObj', contentObj);
  }

  /**
   * 添加预加载图片
   */
  initImg() {
    const contentObj = this.data.contentObj;
    if (!contentObj) {return;}
    if (contentObj) {
      const picArr = this.data.contentObj.picArr;
      if (picArr) {
        for (let i = 0; i < picArr.length; i++ ) {
          const picUrl = picArr[i].pic_url;
          if (picUrl) {
            this.rawImages.set(picUrl, picUrl);
          }
        }
      }
    }
  }

  /**
   * 添加预加载音频
   */
  initAudio() {
    const contentObj = this.data.contentObj;
    const picArr = contentObj.picArr;
    if (contentObj) { return; }
    const addUrlToAudioObj = (audioUrl) => {
      if (audioUrl) {
        const audio = new Audio();
        audio.src = audioUrl;
        audio.load();
        this.audioObj[audioUrl] = audio;
      }
    };
    if (picArr) {
      for (let i = 0; i < picArr.length; i++) {
        addUrlToAudioObj(picArr[i].audio_url);
      }
    }
    addUrlToAudioObj(contentObj.audio_url);
    const audioObj = this.audioObj;
    const addOneAudio = (key, url, vlomue = 1, loop = false, callback = null) => {
      const audio = new Audio();
      audio.src = url;
      audio.load();
      audio.loop = loop;
      audio.volume = vlomue;
      audioObj[key] = audio;
      if (callback) {
        audio.onended = () => {
          callback();
        };
      }
    };
    addOneAudio('finish', this.rawAudios.get('finish'), 0.5);
    addOneAudio('star', this.rawAudios.get('star'), 1);
    addOneAudio('wrong', this.rawAudios.get('wrong'), 1);
    addOneAudio('click', this.rawAudios.get('click'), 1);
  }

  /**
   * 初始化数据
   */
  initData() {
    this.canvasWidth = this.wrap.nativeElement.clientWidth;
    this.canvasHeight = this.wrap.nativeElement.clientHeight;
    this.canvas.nativeElement.width = this.wrap.nativeElement.clientWidth;
    this.canvas.nativeElement.height = this.wrap.nativeElement.clientHeight;

    const sx = this.canvasWidth / this.canvasBaseW;
    const sy = this.canvasHeight / this.canvasBaseH;
    const s = Math.min(sx, sy);
    this.mapScale = s;
    this.renderArr = [];
    this.canTouch = true;
    this.downFlag = false;
    this.showSoundFlag = false;
    this.endPageArr = [];
    this.endRectArr = [];
    this.curPageIndex = 0;

    if (!this.data.contentObj.picArr) {
      this.data.contentObj.picArr = [];
    }
    this.picArr = this.data.contentObj.picArr;
    if (!this.picArr) {return};
    this.picArr.forEach(ele => {
      for (let i = 0; i < ele.wordArr.length; i++) {
        ele.wordArr[i].id = i;
      }
    });
    this.picIndex = 0;
  }

  /**
   * 初始化试图
   */
  initView() {

    this.initBg();
    this.initTitle();
    this.initCard();
    this.initSpot();
    this.initOptions();
    this.initSound();
    this.defaultShow();
    this.isHideCheck();
    this.typeA[0]['isHide'] = false;
    this.typeA[0].alpha = 1;
    console.log('wordArr',this.wordArr);
    console.log('wordArrBg',this.wordArrBg);
  }


  initBaseBg() {
    this.bgArr = [];
    const bg = new MySprite();
    bg.init(this.images.get('Rectangle@2x'));
    bg.x = this.canvasWidth / 2;
    bg.y = this.canvasHeight / 2;
    const sx = this.canvasWidth / bg.width;
    const sy = this.canvasHeight / bg.height;
    const s = Math.max(sx, sy);
    bg.setScaleXY(1);
    this.renderArr.push(bg);
  }

  /**
   * 界面背景图片
   */
  initBg() {
    this.bgArr = [];
    const bg = new MySprite();
    bg.init(this.images.get('Rectangle@2x'));
    bg.x = this.canvasWidth / 2;
    bg.y = this.canvasHeight / 2;
    const sx = this.canvasWidth / bg.width;
    const sy = this.canvasHeight / bg.height;
    const s = Math.max(sx, sy);
    bg.setScaleXY(1);
    this.renderArr.push(bg);

    this.bgLayer = new MySprite();
    this.renderArr.push(this.bgLayer);

    const particleLayer = new MySprite();
    particleLayer.width = this.canvasWidth;
    particleLayer.height = this.canvasHeight;
    this.particleLayer = particleLayer;
  }

  initTitle() {

    // test
    const bgRect = new ShapeRect();
    bgRect.setSize(57, 65);
    bgRect.fillColor = '#FFF';
    const asx = this.canvasWidth / this.canvasBaseW;
    const asy = this.canvasHeight / this.canvasBaseH;
    bgRect.setScaleXY(asx);
    bgRect.x = 65 * asx;
    this.renderArr.push(bgRect);

    const titleBox = new ShapeRect();
    titleBox.init();
    titleBox.fillColor = '#ffffff';
    titleBox.setSize(this.canvasBaseW, 130 * this.mapScale);
    this.renderArr.push(titleBox);
    titleBox.alpha = 0;

    const panel = new ShapeRect();
    panel.fillColor = '#AB5B22';
    panel.setSize(57, 65);
    panel.setScaleXY(asx);
    // panel.init(this.images.get('Rectangle_3@2x'));
    // panel.setScaleXY(this.mapScale * .5);
    panel.x = 65 * asx;
    panel.y = 0;
    this.renderArr.push(panel);
    titleBox.addChild(panel);

    const richText1 = new RichText();
    richText1.disH = 15;
    richText1.text = 'C';
    richText1.x = panel.width / 2 - 24;
    richText1.y = -25;
    // richText1.width = panel.width;
    richText1.fontName = 'BRLNSDB';
    
    // rit
    // richText1.textAlign = 'center';
    // richText1.fontSize = 40;
    richText1.fontColor = '#F7CB47';
    // richText1.x = 35 * asx;
    // richText1.fontWeight = 300 * this.mapScale;
    panel.addChild(richText1);


    const richText2 = new Label();
    const sx = this.canvasWidth / richText2.width;
    const sy = this.canvasHeight / richText2.height;
    const s = Math.max(sx, sy);
    // richText2.setScaleXY(1);
    richText2.setScaleXY(s);
    richText2.text = this.data.contentObj.question_text;
    richText2.fontName = 'BRLNSDB';
    richText2.fontSize = 50 * this.mapScale;
    richText2.fontColor = '#000000';
    richText2.fontWeight = 300;
    richText2.textAlign = 'left';
    richText2.x = 150 * this.mapScale;
    richText2.y = 30 * this.mapScale;
    this.renderArr.push(richText2);
    this.question = titleBox;
    // titleBox.addChild(richText2);
  }

  initCard() {
    this.typeA = [];
    for (let i = 0; i < this.picArr.length; i++) {
      const topH = 60 * this.mapScale;
      const bottomH = 250 * this.mapScale;
      const maxH = this.canvasHeight - topH - bottomH;
      const maxW = this.canvasWidth * 0.9;

      const curData = this.picArr[i];
      
      const panel = new MySprite();
      panel.init(this.images.get(curData.pic_url));
      // panel.setScaleXY(this.mapScale);
      // panel.anchorY = 1;
      let targetY = this.canvasHeight - bottomH;
      if (this.canvasHeight - bottomH > panel.height * panel.scaleY) {
        targetY = panel.height * panel.scaleY;
      }

      const edge = 20 * this.mapScale;
      const sx = (maxW - edge * 2) / panel.width;
      const sy = (maxH - edge * 2) / panel.height;
      const s = Math.min(sx, sy);
      panel.setScaleXY(s);
      
      const qBg = new ShapeRect();
      qBg.init();
      qBg.fillColor = '#ffffff';
      qBg.setSize((panel.width) * panel.scaleX + edge * 2, (panel.height) * panel.scaleY + edge * 2);
      qBg.x = this.canvasWidth / 2;
      qBg.y = topH + qBg.height / 2;
      qBg.setShadow(0, 10 * this.mapScale, 12 * this.mapScale, 'rgba(0, 0, 0, 0.4)');
      this.renderArr.push(qBg);

      qBg.addChild(panel);
      qBg.alpha = 0;


      // panel.x = this.canvasWidth / 2;
      // panel.y = targetY;
      // this.renderArr.push(panel);

      panel['type'] = 'A';
      panel['isHide'] = true;
      this.typeA.push(panel);
    }
    // this.createCard();
  }

  // createCard() {
  //   const topH = 380 * this.mapScale;
  //   const bottomH = 220 * this.mapScale;
  //   const maxH = this.canvasHeight - topH - bottomH;
  //   const maxW = this.canvasWidth * 0.9;

  //   const card = new ShapeRect(this.ctx);
  //   let targetY = this.canvasHeight - bottomH;
  //   if (this.canvasHeight - bottomH > card.height * card.scaleY) {
  //     targetY = card.height * card.scaleY;
  //   }
  //   card.x = this.canvasWidth / 2;
  //   card.y = this.canvasHeight / 2;
  //   card.color = "#FFF";
  //   this.addPic(card);
  //   this.renderArr.push(card);
  // }

  // addPic(card) {
  //   this.typeA = [];
  //   for (let i = 0; i < this.picArr.length; i++) {
  //     const curData = this.picArr[i];
  //     const pic = new MySprite(this.ctx);
  //     pic.init(this.images.get(curData.pic_url));
  //     console.log('hight',pic.height);
  //     pic['type'] = 'A';
  //     pic['isHide'] = true;
  //     this.typeA.push(pic);
  //     card.addChild(pic);
  //   }
  // }

  initSpot() {
    this.spotList = [];
    const picArr = this.data.contentObj.picArr;
    if (!picArr) { return; }
    const arr = this.picArr;
    let spotW = this.spotW + 7;
    let disW = 10;
    let totalW = 0;
    let stotalW = 0;
    if (arr.length <= 8) {
      // totalW = itemW * arr.length + disW * (arr.length - 1);
      stotalW = spotW * arr.length + disW * (arr.length - 1);
    } else {
      // totalW = (itemW + disW) * 8;
      stotalW = (spotW + disW) * 8;
      spotW = stotalW / this.wordList.length / 15 * 14;
    }

    disW = spotW / 14;
    stotalW *= this.mapScale;
    spotW *= this.mapScale;
    disW *= this.mapScale;

    // const itemH = itemW / this.itemW * this.itemH;
    const offX = this.canvasWidth / 2 - stotalW / 2 + (spotW + disW) / 2;

    const disH = 100 * this.mapScale;
    // const offY = this.canvasHeight - (disH) * 2 + itemH / 2;
    this.disW = disW;
    for (let i = 0; i < picArr.length; i++) {
      const baseX = offX + i * (spotW + disW);
      const spot = new ShapeCircle(this.ctx);
      spot.init();
      spot.setScaleXY(this.mapScale * 0.6);
      spot.x = baseX;
      // spot.y = offY + 45 * this.mapScale;
      spot.y = this.canvasHeight - 230 * this.mapScale;
      spot['isChange'] = false;
      spot.fillColor = '#832F27';
      spot.setRadius(40);
      this.renderArr.push(spot);
      // this.space += 120;

      const richText3 = new Label();
      richText3.text = (i + 1).toString();
      richText3.fontName = 'BRLNSDB';
      richText3.fontSize = 65 * this.mapScale;
      richText3.fontColor = '#FFFFFF';
      richText3.textAlign = 'center';
      spot.addChild(richText3);
      this.spotList.push(spot);
    }

  }

  isHideCheck() {
    for (let i = 0; i < this.typeA.length; i++) {
      if (this.typeA[i]['isHide'] == true) {
        this.typeA[i].alpha = 0;
      } else {
        this.typeA[i].alpha = 1;
      }
    }
    for (let i = 0; i < this.spotList.length; i++) {
      if (this.spotList[i]['isChange'] == true) {
        this.spotList[i]['fillColor'] = '#FFFFFF';
        this.spotList[i].children[1]['fontColor'] = '#000000';
        this.spotList[i]['radius'] = '48';
      } else {
        this.spotList[i]['fillColor'] = '#832F27';
        this.spotList[i].children[1]['fontColor'] = '#FFFFFF';
        this.spotList[i]['radius'] = '40';
      }
    }
  }

  byTypeChange(num) {
    for (let i = 0; i < this.typeA.length; i++) {
      this.typeA[i]['isHide'] = true;
    }

    for (let i = 0; i < this.spotList.length; i++) {
      this.spotList[i]['isChange'] = false;
    }

    for (let i = 0; i < this.typeB.length; i++) {
      if (this.typeB[i]['num'] == num) {
        this.typeB[i].alpha = 1;
        this.typeB[i].visible = true;
      } else {
        this.typeB[i].alpha = 0;
        this.typeB[i].visible = false;
      }
    }

    for (let i = 0; i < this.typeC.length; i++) {
      if (this.typeC[i]['num'] == num) {
        this.typeC[i].alpha = 1;
        this.typeC[i].visible = true;
      } else {
        this.typeC[i].alpha = 0;
        this.typeC[i].visible = false;
      }
    }

    this.typeA[num]['isHide'] = false;
    this.spotList[num]['isChange'] = true;
  }

  initOptions() {
    this.wordArr = [];
    this.typeB = [];
    this.typeC = [];

    for ( let i = 0; i < this.picArr.length; i++ ) {
      this.wordArr.push(this.picArr[i].wordArr);
      this.wordArrBg.push(this.picArr[i].wordArr);
    }

    for (let j = 0; j < this.wordArr.length; j++) {
      this.wordList = randomSortByArr(this.wordArr[j]);
      this.wordBgList = this.wordArrBg[j];
      const arr = this.wordList;
      const arrBg = this.wordBgList;
      console.log('arr', arr);
      console.log('arrBg', arrBg);
      let itemW = this.itemW + 7;
      let disW = 10;
      let totalW = 0;
      if (arr.length <= 8) {
        totalW = itemW * arr.length + disW * (arr.length - 1);
      } else {
        totalW = (itemW + disW) * 8;
        itemW = totalW / this.wordList.length / 15 * 14;
      }
  
      disW = itemW / 14;
      totalW *= this.mapScale;
      itemW *= this.mapScale;
      disW *= this.mapScale;
  
      const itemH = itemW / this.itemW * this.itemH;
      const offX = this.canvasWidth / 2 - totalW / 2 + (itemW + disW) / 2;
  
      const disH = 100 * this.mapScale;
      const offY = this.canvasHeight - (disH) * 2 + itemH / 2;
      this.disW = disW;
  
      for (let k = 0; k < arr.length; k++) {
        const baseX = offX + k * (itemW + disW);
        const data = arr[k];
        const dataBg = arrBg[k];
        const optionRect = new ShapeRect();
        optionRect.init();
        optionRect.fillColor = '#ffffff';
        optionRect.setSize(itemW, itemH);
        optionRect.setShadow(0, 5, 10);
        optionRect.x = baseX;
        optionRect.y = this.canvasHeight - 55 * this.mapScale;
        optionRect['id'] = data.id;
        optionRect['data'] = data;
        optionRect['baseX'] = optionRect.x;
        optionRect['baseY'] = optionRect.y;
        optionRect['num'] = j;
        optionRect['isHide'] = true;
        this.renderArr.push(optionRect);
        this.optionRect = optionRect;
  
        const optionBg = new MySprite();
        optionBg.init(this.images.get('Word_Card_Box@2x'));
        optionRect.setSize(itemW, itemH);
        optionBg.setScaleXY(this.mapScale * .5);
        optionBg.x = optionRect.x;
        optionBg.y = this.canvasHeight - 150 * this.mapScale;
        optionBg['id'] = k;
        optionBg['num'] = j;
        optionBg['data'] = dataBg;
        this.renderArr.push(optionBg);
  
        const label = new Label();
        label.text = data.text;
        label.fontSize = 42 * this.mapScale;
        label.fontColor = '#20A895';
        label.textAlign = 'center';
        label.fontName = 'BRLNSDB';
        label.setMaxSize(optionRect.width - 20);
        optionRect.addChild(label);
  
        const outline = new LineRect();
        outline.init();
        outline.lineWidth = 5 * this.mapScale;
        outline.setSize(optionRect.width, optionRect.height);
        outline.lineColor = '#31F3D3';
        optionRect.addChild(outline);
        outline.alpha = 0;
        optionRect['outline'] = outline;
  
        const topRect = new ShapeRect();
        topRect.init();
        topRect.fillColor = '#925af7';
        topRect.setSize(optionRect.width, optionRect.height);
        optionRect.addChild(topRect);
        optionRect['topRect'] = topRect;
        topRect.visible = false;
        topRect.alpha = 0;
        topRect.childDepandAlpha = true;
        this.topRect = topRect;
        
        this.typeB.push(optionRect);
        this.typeC.push(optionBg);
      }
    }

  }

  getArr(num) {
    this.optionRectArr = [];
    this.optionRectArrBak = [];
    this.optionBgArr = [];
    for (let i = 0; i < this.typeB.length; i++) {
      if (this.typeB[i]['num'] == num) {
        this.optionRectArr.push(this.typeB[i]);
      }
    }

    for (let i = 0; i < this.typeC.length; i++) {
      if (this.typeC[i]['num'] == num) {
        this.optionBgArr.push(this.typeC[i]);
      }
    }
    
    for (let i = 0; i < this.optionRectArr.length; i++) {
      let id = this.optionRectArr[i]['id'];
      let xPos = this.optionRectArr[i]['x'];
      let yPos = this.optionRectArr[i]['y'];
      let num = this.optionRectArr[i]['num'];
      let newRect = [];
      newRect.push(id);
      newRect.push(xPos);
      newRect.push(yPos);
      newRect.push(num);
      this.optionRectArrBak.push(newRect);
    }
  }

  defaultShow() {
    for (let i = 0; i < this.typeB.length; i++) {
      this.typeB[i].alpha = 0;
      this.typeB[i].visible = false;
    }

    for (let i = 0; i < this.typeC.length; i++) {
      this.typeC[i].alpha = 0;
      this.typeC[i].visible = false;
    }
    
    for (let i = 0; i < this.typeB.length; i++) {
      if (this.typeB[i]['num'] == 0) {
        this.typeB[i].alpha = 1;
        this.typeB[i].visible = true;
      } 
    }
    
    for (let i = 0; i < this.typeC.length; i++) {
      if (this.typeC[i]['num'] == 0) {
        this.typeC[i].alpha = 1;
        this.typeC[i].visible = true;
      } 
    }

    this.spotList[0]['isChange'] = true;
    this.isHideCheck();
    this.getArr(0);
  }

  initPic() {
    const maxW = this.canvasWidth * 0.7;
    const pic1 = new MySprite();
    pic1.init(this.images.get(this.data.pic_url));
    pic1.x = this.canvasWidth / 2;
    pic1.y = this.canvasHeight / 2;
    pic1.setScaleXY(maxW / pic1.width);
    this.renderArr.push(pic1);
    this.pic1 = pic1;

    const label1 = new Label();
    label1.text = this.data.text;
    label1.textAlign = 'center';
    label1.fontSize = 50;
    label1.fontName = 'BRLNSDB';
    label1.fontColor = '#ffffff';
    pic1.addChild(label1);

    const pic2 = new MySprite();
    pic2.init(this.images.get(this.data.pic_url_2));
    pic2.x = this.canvasWidth / 2 + this.canvasWidth;
    pic2.y = this.canvasHeight / 2;
    pic2.setScaleXY(maxW / pic2.width);
    this.renderArr.push(pic2);
    this.pic2 = pic2;
    this.curPic = pic1;
  }

  showWord() {
    this.wordArr = this.wordArr[this.picIndex];
    console.log('RandomID', this.wordArr);
    const arr = this.wordArr;
    let itemW = this.itemW;
    let disW = 10;
    let totalW = 0;
    if (arr.length <= 8) {
      totalW = (itemW + disW) * this.picArr.length;
    } else {
      totalW = (itemW + disW) * 8;
      itemW = totalW / this.picArr.length / 15 * 14;
    }

    disW = itemW / 14;
    totalW *= this.mapScale;
    itemW *= this.mapScale;
    disW *= this.mapScale;

    const itemH = itemW / this.itemW * this.itemH;
    const offX = this.canvasWidth / 2 - totalW / 2 + (itemW + disW) / 2;

    const disH = 100 * this.mapScale;
    const offY = this.canvasHeight - (disH) * 2 + itemH / 2;
    this.disW = disW;

    for (let i = 0; i < arr.length; i++) {
      const data = arr[i];
      console.log('initOption', data);
      const label = new Label();
      label.text = data.text;
      label.fontSize = 42 * this.mapScale;
      label.fontColor = '#fe5e22';
      label.textAlign = 'center';
      label.fontName = 'BRLNSDB';
      label.setMaxSize(this.optionRect.width - 20);
      this.topRect.addChild(label);
  }
}

  soundBegin(i) {
    const curData = this.picArr[i];
    if (!curData.audio_url) { return; }
    const audioLink = curData.audio_url;
    this.audioPlayer.src = audioLink;
    this.audioPlayer.load();
    if (this.showSoundFlag === true) {
      this.audioPlayer.play();
    } else {
      this.audioPlayer.pause();
    }
    this.audioPlayer.onended = () => {
      this.showSoundFlag = !this.showSoundFlag;
      this.soundCheck();
    };
  }

  questionSoundBegin() {
    const audioLink = this.data.contentObj.question_audio;
    console.log(audioLink);
    this.audioRect.src = audioLink;
    this.audioRect.load();
    this.audioRect.play();
  }


  initSound() {
    const soundClose = new MySprite();
    soundClose.init(this.images.get('Sound_Close_Btn@2x'));
    soundClose.x = this.canvasWidth - 70 * this.mapScale;
    soundClose.y = this.canvasHeight - 50 * this.mapScale;
    soundClose.setScaleXY(this.mapScale * .5);
    this.renderArr.push(soundClose);
    this.soundClose = soundClose;

    const soundOpen = new MySprite();
    soundOpen.init(this.images.get('Sound_Open_Btn@2x'));
    soundOpen.setScaleXY(this.mapScale);
    soundOpen.x = soundClose.x;
    soundOpen.y = soundClose.y;
    soundOpen.setScaleXY(this.mapScale * .5);
    this.renderArr.push(soundOpen);
    this.soundOpen = soundOpen;
    soundClose.visible = false;
    soundOpen.visible = true;
  }

  soundCheck() {
    if (this.showSoundFlag) {
      this.soundClose.visible = true;
      this.soundOpen.visible = false;
    } else {
      this.soundClose.visible = false;
      this.soundOpen.visible = true;
    }
  }

  clickOptionRect(optionRect) {
    if (this.curOptionRect && this.curOptionRect !== optionRect) {
      this.hideOutLine(this.curOptionRect);
    }

    this.curOptionRect = optionRect;
    removeItemFromArr(this.renderArr, optionRect);
    this.renderArr.push(optionRect);
    this.showOutLine(this.curOptionRect);
    this.wordSound(this.curOptionRect);
    const data = optionRect.data;
    this.playAudio(data.audio_url, true);
  }

  wordSound(optionRect) {
    const clickLink: any = this.rawAudios.get('click');
    this.audioClick.src = clickLink;
    this.audioClick.load();
    this.audioClick.play();
    this.audioClick.onended = () => {
      if (!optionRect) {
        return;
      }
      const wordAudio = optionRect.data.audio_url;
      if (!wordAudio) {
        return;
      }
      this.audioWord.src = wordAudio;
      this.audioWord.load();
      this.audioWord.play();
    };
  }

  hideOutLine(optionRect) {
    hideItem(optionRect.outline, 0.2);
  }

  showOutLine(optionRect) {
    showItem(optionRect.outline, 0.2);
  }

  clickOptionTarget(optionTarget) {
    this.curOptionTarget = optionTarget;
    if (!this.curOptionRect) {
      return;
    }

    if (this.curOptionRect.id == optionTarget.id) {
      this.canTouch = false;
      moveItem(this.curOptionRect, optionTarget.x, optionTarget.y, 0.3, () => {
        this.canTouch = true;
        this.putOption(this.curOptionRect, optionTarget);
      }, TWEEN.Easing.Cubic.Out);
    } else {
      this.playAudio('wrong', true);
      shake(this.curOptionRect, 0.4);
    }
  }

  putOption(option, optionTarget) {
    option.x = optionTarget.x;
    option.y = optionTarget.y;

    removeItemFromArr(this.optionRectArr, option);
    this.sortOptionRectArr();
    showPopParticle(this.images.get('star'), {x: option.x, y: option.y}, this.particleLayer);
    this.hideOutLine(this.curOptionRect);
    this.curOptionRect = null;
    this.endRectArr.push(option);
    this.checkEnd();

    const startLink: any = this.rawAudios.get('star');
    this.audioRect.src = startLink;
    this.audioRect.load();
    this.audioRect.play();
  }

  checkEnd() {
    console.log(' show end petal', this.optionRectArr.length);
    if (this.optionRectArr.length <= 0) {
      console.log(' show end petal!!!', this.optionRectArr.length);
      this.finishTag();
      this.gameEnd();
    } 
  }

  sortOptionRectArr() {
    for (let i = 0; i < this.optionRectArr.length; i++) {
      if (this.optionRectArr[i]['status'] === 'finish') {
        return;
      }
    }

    const arr = this.optionRectArr;
    if (arr.length > 0) {
      this.canTouch = false;
      const itemW = arr[0].width;
      let disW = this.disW;
      const totalW = itemW * arr.length + disW * (arr.length - 1);
      const offX = this.canvasWidth / 2 - totalW / 2 + (itemW + disW) / 2;

      const time = 0.4;
      for (let i = 0; i < arr.length; i++) {
        arr[i].baseX = offX + i * (itemW + disW);
        moveItem(arr[i], arr[i].baseX, arr[i].baseY, time, null, TWEEN.Easing.Cubic.Out);
      }

      setTimeout(() => {
        this.canTouch = true;
      }, time * 1000);
    }
  }

  sortOptionBgArr() {
    const arr1 = this.optionBgArr;
    if (arr1.length > 0) {
      this.canTouch = false;

      const itemW = arr1[0].width;
      let disW = this.disW;

      const totalW = itemW * arr1.length + disW * (arr1.length - 1);
      const offX = this.canvasWidth / 2 - totalW / 2 + (itemW + disW) / 2;

      const time = 0.4;
      for (let i = 0; i < arr1.length; i++) {
        arr1[i].baseX = offX + i * (itemW + disW);
        moveItem(arr1[i], arr1[i].baseX, arr1[i].baseY, time, null, TWEEN.Easing.Cubic.Out);
      }

      setTimeout(() => {
        this.canTouch = true;
      }, time * 1000);
    }
  }

  checkOnOptionTarget() {
    for (let i = 0; i < this.optionBgArr.length; i++) {
      if (this.checkPointInRect(this.mx, this.my, this.optionBgArr[i].getBoundingBox())) {
        this.checkOptionTargetRight(this.optionBgArr[i]);
        return;
      }
    }
    this.optionResetPos();
  }

  optionResetPos() {
    if (this.curOptionRect) {
      this.canTouch = false;
      moveItem(this.curOptionRect, this.curOptionRect.baseX, this.curOptionRect.baseY, 0.3, () => {
        this.canTouch = true;
      }, TWEEN.Easing.Back.Out);
    }
  }

  checkOptionTargetRight(optionTarget) {
    console.log('curOptionRect',this.curOptionRect);
    console.log('optionTarget',optionTarget);
    console.log('curOptionRect.text',this.curOptionRect.data['text']);
    // console.log('optionTarget.text',optionTarget.data['text']);
    console.log('curOptionRect.id',this.curOptionRect.id);
    console.log('optionTarget.id',optionTarget.id);
    // || this.curOptionRect.data['text'] == optionTarget.data['text']
    if (this.curOptionRect.id == optionTarget.id || this.curOptionRect.data['text'] == optionTarget.data['text']) {
      this.putOption(this.curOptionRect, optionTarget);
    } else {
      const wrongLink: any = this.rawAudios.get('wrong');
      this.audioRect.src = wrongLink;
      this.audioRect.load();
      this.audioRect.play();
      this.optionResetPos();
    }
  }

  getPos() {
    if (this.endRectArr.length !== 0) {
      this.endRectArr.forEach(ele => {
        let oldId = ele['id'];
        let endRect = ele;
        for (let i = 0; i < this.optionRectArrBak.length; i++) {
          if (this.optionRectArrBak[i]['0'] === oldId) {
            let xPos = this.optionRectArrBak[i]['1'];
            let yPos = this.optionRectArrBak[i]['2'];
            moveItem(endRect, xPos, yPos, 0.3, () => {
              removeItemFromArr(this.endRectArr, endRect);
            }, TWEEN.Easing.Cubic.Out);
          }
        }
      });
    }
  }

  finishTag() {
    let num = this.optionRectArrBak[0]['3'];
    for (let i = 0; i < this.typeB.length; i++) {
      if (this.typeB[i]['num'] == num) {
        this.typeB[i]['status'] = 'finish';
      }
    }
  }

  checkTag() {
    let num = this.optionRectArrBak[0]['3'];
    for (let i = 0; i < this.typeB.length; i++) {
      if (this.typeB[i]['num'] == num) {
        if (this.typeB[i]['status'] === 'finish') {
          console.log('finished it!');
        } else {
          console.log('no finished');
          this.sortOptionRectArr(); 
        }
      }
    }
  }

  clickSound() {
    const clickLink: any = this.rawAudios.get('click');
    this.audioRect.src = clickLink;
    this.audioRect.load();
    this.audioRect.play();
  }

  mapDown(event) {
    if (!this.canTouch) {
      return;
    }

    this.downFlag = true;
    this.curOptionTarget = null;

    for (let i = 0; i < this.endRectArr.length; i++) {
      if (this.checkClickTarget(this.endRectArr[i])) {
        const data = this.endRectArr[i].data;
        return;
      }
    }

    for (let i = 0; i < this.optionRectArr.length; i++) {
      if (this.checkClickTarget(this.optionRectArr[i])) {
        this.clickOptionRect(this.optionRectArr[i]);
        return;
      }
    }

    for (let i = 0; i < this.optionBgArr.length; i++) {
      if (this.checkClickTarget(this.optionBgArr[i])) {
        this.clickOptionTarget(this.optionBgArr[i]);
        return;
      }
    }

    for (let i = 0; i < this.spotList.length; i++) {
      if (this.checkClickTarget(this.spotList[i])) {
        this.sortOptionRectArr();
        this.byTypeChange(i);
        this.isHideCheck();

        if (this.endRectArr.length > 0 && this.endRectArr.length < this.optionRectArrBak.length) {
          this.getPos();
        }
        if (this.endRectArr.length == this.optionRectArrBak.length) {
          this.endRectArr = [];
        }   

        this.checkTag();
        this.getArr(i);
        this.sortOptionRectArr();
        this.soundID = i;
        this.picIndex = i;
        this.audioPlayer.pause();
        this.soundCheck();
        this.clickSound();
        return;
      }
    }

    if (this.checkClickTarget(this.soundClose)) {
      this.showSoundFlag = !this.showSoundFlag;
      console.log(this.showSoundFlag);
      this.soundCheck();
      this.soundBegin(this.picIndex);
      return;
    }

    if (this.checkClickTarget(this.soundOpen)) {
      this.showSoundFlag = !this.showSoundFlag;
      console.log(this.showSoundFlag);
      this.soundCheck();
      this.soundBegin(this.picIndex);
      return;
    }

    if (this.checkClickTarget(this.question)) {
      this.questionSoundBegin();
      return;
    }

    this.downFlag = false;
  }

  mapMove(event) {
    if (!this.curOptionRect) {
      return;
    }

    if (!this.downFlag) {
      return;
    }

    this.curOptionRect.x = this.mx;
    this.curOptionRect.y = this.my;
  }

  mapUp(event) {
    this.downFlag = false;
    if (this.curOptionRect) {
      if (!this.curOptionTarget) {
        this.checkOnOptionTarget();
      }
    }

    this.curOptionTarget = null;
  }

  update() {
    this.animationId = window.requestAnimationFrame(this.update.bind(this));
    // 清除画布内容
    this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
    // tween 更新动画
    TWEEN.update();
    this.updateArr(this.renderArr);
    this.updateItem(this.particleLayer);
    this.updateArr(this.endPageArr);
  }

  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;
  }
}
