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

import {
  MySprite,
  Label,
  moveItem,
  rotateItem,
  removeItemFromArr,
  ShapeRect, scaleItem, tweenChange, showPopParticle, hideItem, showItem, LineRect, shake, ShapeRectNew,

} from './Unit';
import {res, resAudio} from './resources';

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

import * as _ from 'lodash';
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;

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

  get data() {
    return this._data;
  }

  @Input()
  sid;

  @ViewChild('canvas') canvas: ElementRef;
  @ViewChild('wrap') wrap: ElementRef;
  canvasWidth = 1280;
  canvasHeight = 720;

  canvasBaseW = 1280;
  canvasBaseH = 720;

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

  mx;
  my; // 点击坐标

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

  images = new Map();

  animationId: any;
  winResizeEventStream = new Subject();

  audioObj = {};
  renderArr;
  mapScale = 1;

  canvasLeft;
  canvasTop;

  canTouch = true;

  KEY = 'hw_online_008';

  // -----
  picArr;
  titleLabel;
  light;
  particleLayer;
  shadowArr;
  answerTarget;
  answerCurrent;
  bgRect;
  starBgArr;
  clickedSuccessArr;

  pageLabel;
  leftBtn;
  rightBtn;
  bgLayer;
  curPageIndex;

  hotZoneArr;

  picIndex = 0;

  bgArr;
  endPageArr;
  gameEndFlag;
  showPetalFlag;
  bg;

  // 是否游戏进行中
  isGaming;

  serverAllUser;

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

  teachFlag;
  coverPageArr = [];
  startBtn;

  ngOnInit() {
    const getData = (<any> window).courseware.getData;
    getData((data, aspect) => {


      if (aspect) {
        console.log('aspect : ', aspect);
        this.serverAllUser = aspect.all_user;
      }

      if (window['air'].airClassInfo.user.classRole == 'tea') {
        this.teachFlag = true;
      }
      if (data && typeof data == 'object') {
        this.data = data;
      } else {
        this.data = {};
      }

      // this.addServerListener();

      console.log('data:', data);
      if (!this.data.contentObj) {
        this.data.contentObj = {};
      }

      this.initDefaultData();
      this.initAudio();
      this.initImg();
      this.initListener();

    }, this.KEY);
  }

  initCover() {
    const shapeBg = new ShapeRectNew();
    const lenW = 400 * this.mapScale;
    shapeBg.setSize(lenW, lenW / 3 * 1.5, 30 * this.mapScale);
    shapeBg.alpha = 0.5;
    shapeBg.fillColor = '#000000';
    shapeBg.x = this.canvasWidth / 2 - shapeBg.width / 2;
    shapeBg.y = this.canvasHeight / 2 - shapeBg.height / 2;
    this.coverPageArr.push(shapeBg);
    this.startBtn = shapeBg;

    const label = new Label();
    label.fontName = 'BRLNSDB';
    label.fontColor = '#ffffff';
    label.fontSize = 50;
    label.textAlign = 'center';
    label.x = shapeBg.width / 2;
    label.y = shapeBg.height / 2;
    shapeBg.addChild(label);

    if (this.teachFlag) {
      label.text = 'start';
    } else {
      label.text = 'ready ..';
    }
  }

  initDefaultData() {
    let picArr = this.data.contentObj.picArr;
    // console.log('picArr: ', picArr);
    if (!picArr || picArr.length == 0) {
      const bgItem = {
        rect: {
          height: 472,
          width: 839.8576512455516,
          x: 222.57117437722422,
          y: 0
        },
        url: 'assets/play/default/pic.jpg'
      };

      const hotZoneItemArr = [
        {
          index: 0,
          key: '1575362511657',
          rect: {
            height: 103.49,
            width: 115.49,
            x: 481.21,
            y: 316
          }
        },

        {
          index: 1,
          key: '1575362515047',
          rect: {
            height: 119.08,
            width: 119.08,
            x: 257.3,
            y: 312.99
          }
        },

        {
          index: 2,
          key: '1575363832858',
          rect: {
            height: 107.35,
            width: 108.66,
            x: 415.77,
            y: 199
          }
        },

        {
          index: 3,
          key: '1575515846460',
          rect: {
            height: 103,
            width: 103,
            x: 709.43,
            y: 319.5
          }
        }
      ];

      let picArr = [];
      for (let i = 0; i < 3; i++) {

        const pic = {};

        const options = JSON.parse(JSON.stringify(hotZoneItemArr));
        switch (i) {
          case 0:
            options[0].checked = true;
            pic['text'] = 'Where is the pig ?';
            break;
          case 1:
            options[1].checked = true;
            pic['text'] = 'Where is the fish ?';
            break;
          case 2:
            options[2].checked = true;
            options[3].checked = true;
            pic['text'] = 'Please find the fruit .';
            break;
        }

        pic['options'] = options;
        picArr.push(pic);

      }
      //
      // const picArr = [];
      // for (let i = 0; i < 2; i++) {
      //   picArr.push({
      //     'pic_url': 'assets/play/default/pic.jpg',
      //     'audio_url': 'assets/play/default/audio.mp3'
      //   });
      // }

      this.data.contentObj.picArr = picArr;
      this.data.contentObj.bgItem = bgItem;
      this.data.contentObj.hotZoneItemArr = hotZoneItemArr;

    }


  }

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

  serverPicArr;

  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.coverPageArr = [];

    console.log(' in initData', this.data);

    this.canTouch = true;
    this.gameEndFlag = false;

    this.curPageIndex = 0;
    this.endPageArr = [];
    this.shadowArr = [];
    this.starBgArr = [];
    if (!this.data.contentObj.picArr) {
      this.data.contentObj.picArr = [];
    }
    this.picArr = this.data.contentObj.picArr;
    this.serverPicArr = JSON.parse(JSON.stringify(this.picArr));

    this.picIndex = 0;
  }

  setServerPicArr(data) {
    const tmpData = this.serverPicArr[this.curPageIndex];
    tmpData.finish = true;
    let score = 0;
    for (let i = 0; i < this.serverPicArr.length; i++) {
      if (this.serverPicArr[i].finish) {
        score++;
      }
    }

    let finishFlag = true;
    for (let i = 0; i < this.serverPicArr.length; i++) {
      if (!this.serverPicArr[i].finish) {
        finishFlag = false;
        break;
      }
    }
    const scoreData = {};
    scoreData['user'] = window['air'].airClassInfo.user;
    scoreData['serverPicArr'] = this.serverPicArr;
    scoreData['score'] = score;
    scoreData['finish'] = finishFlag;
    this.sendServerEvent('score_data', scoreData);
  }


  initAudio() {

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

    const addUrlToAudioObj = (audioUrl) => {
      if (audioUrl) {
        // console.log('audioUrl:', audioUrl);
        const audio = new Audio();
        audio.src = audioUrl;
        audio.load();
        this.audioObj[audioUrl] = audio;
      }
    };

    let arr = contentObj.picArr;

    if (arr) {
      // console.log('arr: ', arr);
      for (let i = 0; i < arr.length; i++) {
        addUrlToAudioObj(arr[i].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('click', this.rawAudios.get('click'), 0.3);
    addOneAudio('right', this.rawAudios.get('right'), 0.3);
    addOneAudio('wrong', this.rawAudios.get('wrong'), 0.3);
    addOneAudio('star', this.rawAudios.get('star'), 1);
    addOneAudio('tip', this.rawAudios.get('tip'), 0.3);
    addOneAudio('finish', this.rawAudios.get('finish'), 0.5);
  }

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

      const addPicUrl = (url) => {
        if (url) {
          this.rawImages.set(url, url);
        }
      };

      let arr = this.data.contentObj.picArr;
      if (arr) {

        for (let i = 0; i < arr.length; i++) {
          addPicUrl(arr[i].pic_url);
        }
      }

      addPicUrl(contentObj.bgItem.url);
    }

    // 预加载资源
    this.loadResources().then(() => {
      this.init();
      this.update();
      this.addServerListener();
      // this.setfontData();
      window['air'].hideAirClassLoading(this.KEY, this.data);

    });
  }

  initFontImg() {


    // const fontbaseUrlW = 'assets/mechanical/letter/';
    // const fontDataW = {};
    //
    // let num = 97;
    // for (let i = 0; i < 26; i++) {
    //
    //   const key = String.fromCharCode(num + i);  // 'a'
    //   const url = fontbaseUrlW + key + '.png';
    //
    //   this.rawImages.set(url, url);
    //   fontDataW[key] = url;
    // }
    //
    //
    // this.fontDataW = fontDataW;
  }

  setfontData() {

    // for (let key in this.fontDataW) {
    //   this.fontDataW[key] = this.images.get(this.fontDataW[key]);
    // }
  }


  init() {
    this.initData();
    this.initCtx();
    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;


  }


  initView() {
    this.initBg();
    this.initHotZone();
    this.initPic();
    this.initTitle();
    this.initLight();
    this.refreshAnswerNum();
    this.initCover();
    this.initTeacherPage();
    this.syncPage();
  }

  syncPage() {

    const allUser = this.serverAllUser;

    if (allUser) {

      console.log('allUser: ', allUser);
      for (let i = 0; i < allUser.length; i++) {
        const userData = allUser[i];
        if (userData.user.classRole == 'tea') {

          if (userData.aspect) {
            const aspect = JSON.parse(userData.aspect);

            console.log('aspect: ', aspect);
            if (aspect.startFlag) {
              this.isGaming = true;

              if (this.teachFlag) {
                this.teacherPage.visible = true;
                this.fillTeacherPageData();
              }
            }
          }
          break;
        }
      }
    }

  }


  fillTeacherPageData() {

    const allUser = this.serverAllUser;

    if (allUser) {

      console.log('allUser 2 : ', allUser);
      for (let i = 0; i < allUser.length; i++) {
        const userData = allUser[i];
        if (userData.user.classRole == 'stu') {

          if (userData.aspect) {
            const aspect = JSON.parse(userData.aspect);

            console.log('aspect: ', aspect);
            this.addTeacherPageData(aspect);
          }
          break;
        }
      }
    }

  }



  teacherPageArr;
  // 这里存放的是数据
  scoreDataArr;
  // 这里存放的是最后ui的映射
  teacherPageListArr;
  teacherPage;
  arrowL;
  arrowR;
  teacherPageLabel;
  curTeacherPage = 1;

  initTeacherPage() {
    this.teacherPageArr = [];
    this.scoreDataArr = [];
    this.teacherPageListArr = [];

    const bg = new MySprite();
    bg.init(this.images.get('bg'));
    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(s);
    bg.visible = false;
    this.teacherPage = bg;
    this.teacherPageArr.push(bg);


    const w = 600;
    const h = 500;
    const lineW = 4 * this.mapScale;
    const frame = new ShapeRectNew();
    frame.setSize(w, h, 20 * this.mapScale);
    frame.fill = false;
    frame.setOutLine('#ffffff', lineW);
    frame.setScaleXY(this.mapScale);
    frame.x = this.canvasWidth / 2 - w * this.mapScale / 2;
    frame.y = this.canvasHeight / 2 - h * this.mapScale / 2 - 20 * this.mapScale;
    this.teacherPageArr.push(frame);


    const pageShowNum = 5;
    const itemH = h - lineW;
    const baseY = lineW / 2;
    for (let i = 0; i < pageShowNum; i++) {

      const listItem = new ShapeRect();
      listItem.setSize(w * 0.96, itemH / pageShowNum * 1);
      listItem.x = (w - listItem.width) / 2;
      listItem.y = baseY + i * itemH / pageShowNum;
      listItem.alpha = 0;
      frame.addChild(listItem);


      const labelNum = new Label();
      labelNum.textAlign = 'center';
      labelNum.fontColor = '#ffffff';
      labelNum.fontName = 'BRLNSDB';
      labelNum.fontSize = 50;
      labelNum.text = i.toString();
      labelNum.x = 50;
      labelNum.y = listItem.height / 2;
      listItem.addChild(labelNum);

      const labelName = new Label();
      labelName.textAlign = 'center';
      labelName.fontColor = '#ffffff';
      // labelName.fontName = 'BRLNSDB';
      labelName.fontSize = 40;
      labelName.text = '张三';
      labelName.x = 220;
      labelName.y = listItem.height / 2;
      listItem.addChild(labelName);

      const labelScore = new Label();
      labelScore.textAlign = 'center';
      labelScore.fontColor = '#ffffff';
      // labelScore.fontName = 'BRLNSDB';
      labelScore.fontSize = 35;
      labelScore.text = Math.floor(Math.random() * 100).toString();
      labelScore.x = 410;
      labelScore.y = listItem.height / 2;
      listItem.addChild(labelScore);

      const labelFinish = new MySprite();
      labelFinish.init(this.images.get('t_right'));
      labelFinish.setScaleXY(0.07);
      labelFinish.x = listItem.width - 30;
      labelFinish.y = listItem.height / 2;
      listItem.addChild(labelFinish);


      if (i != pageShowNum - 1) {
        const line = new ShapeRect();
        line.setSize(listItem.width, lineW);
        line.fillColor = '#ffffff';
        line.y = listItem.height;
        listItem.addChild(line);
      }

      listItem['num'] = labelNum;
      listItem['name'] = labelName;
      listItem['score'] = labelScore;
      listItem['finish'] = labelFinish;

      labelNum.visible = false;
      labelName.visible = false;
      labelScore.visible = false;
      labelFinish.visible = false;

      this.teacherPageListArr.push(listItem);

    }


    const arrowL = new MySprite();
    arrowL.init(this.images.get('t_arrow'));
    arrowL.setScaleXY(this.mapScale * 0.17);
    arrowL.x = this.canvasWidth / 2 - w * 0.3 * this.mapScale;
    arrowL.y = frame.y + frame.height * frame.scaleY + 50 * this.mapScale;
    this.arrowL = arrowL;
    this.teacherPageArr.push(arrowL);


    const arrowR = new MySprite();
    arrowR.init(this.images.get('t_arrow'));
    arrowR.setScaleXY(this.mapScale * 0.17);
    arrowR.x = this.canvasWidth / 2 + w * 0.3 * this.mapScale;
    arrowR.y = frame.y + frame.height * frame.scaleY + 50 * this.mapScale;
    arrowR.scaleX *= -1;
    this.arrowR = arrowR;
    this.teacherPageArr.push(arrowR);

    const pageLabel = new Label();
    pageLabel.textAlign = 'center';
    pageLabel.fontColor = '#ffffff';
    pageLabel.fontName = 'BRLNSDB';
    pageLabel.fontSize = 40 * this.mapScale;
    pageLabel.text = '1 / 1';
    pageLabel.x = this.canvasWidth / 2;
    pageLabel.y = arrowL.y;
    this.teacherPageLabel = pageLabel;
    this.teacherPageArr.push(pageLabel);

    this.curTeacherPage = 1;
  }

  initTitle() {

    const label = new Label();
    label.fontSize = 42 * this.mapScale;
    label.fontName = 'BRLNSDB';
    label.textAlign = 'center';
    label.setMaxSize(this.canvasWidth * 0.9);
    label.x = this.canvasWidth / 2;
    label.y = (this.bgRect.y - this.bgRect.height / 2 * this.bgRect.scaleY) / 2;
    label.fontColor = '#fff143';
    label.setShadow(0, 5, 5, 'rgba(0,0,0,0.3)');
    label.anchorX = 0;
    this.titleLabel = label;
    this.renderArr.push(label);

    const disH = 5 * this.mapScale;


    const starBg = new MySprite();
    starBg.init(this.images.get('top_star_bg'));
    starBg.setScaleXY(this.mapScale);

    const disW = starBg.width / 3 * starBg.scaleX;

    const num = this.picArr.length;
    const itemW = starBg.width * starBg.scaleX;
    const totalW = (starBg.width) * starBg.scaleX * num + disW * (num - 1);
    const offX = this.canvasWidth / 2 - totalW / 2 + itemW / 2;

    this.starBgArr = [];
    for (let i = 0; i < num; i++) {
      const starBg = new MySprite();
      starBg.init(this.images.get('top_star_bg'));
      starBg.setScaleXY(this.mapScale);
      starBg.x = offX + (itemW + disW) * i;
      starBg.y = label.y - starBg.height / 2 * starBg.scaleY - disH / 2;

      this.renderArr.push(starBg);


      const star = new MySprite();
      star.init(this.images.get('top_star'));
      star.visible = false;
      starBg['star'] = star;
      starBg.addChild(star);

      this.starBgArr.push(starBg);
    }


    label.y += label.height / 2 * label.scaleY + disH / 2;


    // const textBg = new MySprite();
    // textBg.init(this.images.get('text_bg'));
    // textBg.setScaleXY(this.mapScale);
    // textBg.x = label.x;
    // textBg.y = label.y - textBg.height / 2 * textBg.scaleY - disH / 2;
    // this.renderArr.push(textBg);
    //
    // label.y += label.height / 2 * label.scaleY + disH / 2;
    //
    //
    // const pageLabel = new Label();
    // pageLabel.text = '0 / 0';
    // pageLabel.fontName = 'BRLNSDB';
    // pageLabel.fontColor = '#ffffff';
    // pageLabel.textAlign = 'center';
    // pageLabel.fontSize = 24;
    // textBg.addChild(pageLabel);
    //
    // this.pageLabel = pageLabel;

    this.refreshTitleLabel();
    this.refreshPageLabel();
  }


  refreshTitleLabel(animaFlag = false) {
    const data = this.picArr[this.curPageIndex];

    if (animaFlag) {

      hideItem(this.titleLabel, 0.2, () => {
        this.titleLabel.text = data.text;
        showItem(this.titleLabel, 0.3);

        this.playAudio('tip', true);

        this.showAudio();

      });
    } else {
      this.titleLabel.text = data.text;

    }

    this.titleLabel.refreshSize();
  }


  refreshPageLabel() {

    // const label = this.pageLabel;
    // label.text = (this.curPageIndex + 1) + ' / ' + this.picArr.length;

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

      const starBg = this.starBgArr[i];
      if (starBg) {
        const star = starBg.star;
        if (!star.visible) {

          star.visible = true;
          star.setScaleXY(3);
          star.alpha = 0;

          tweenChange(star, {scaleX: 1, scaleY: 1, alpha: 1}, 1, () => {

          }, TWEEN.Easing.Exponential.In);

        }

      }

    }
  }

  showAudio() {
    const data = this.picArr[this.curPageIndex];
    const audio = this.audioObj[data.audio_url];
    if (audio) {

      try {
        audio.play();
      } catch (e) {
        console.log('e: ', e);
      }
    }
  }

  initPic() {
  }


  initLight() {
    const light = new LineRect();
    light.init();
    light.visible = false;
    light.setShadow(0, 0, 15 * this.mapScale, 'rgba(255, 255, 0, 1)');
    light.lineWidth = 7 * this.mapScale;
    this.light = light;
    this.renderArr.push(light);
  }

  initBg() {

    this.bgArr = [];

    const bg = new MySprite();
    bg.init(this.images.get('bg'));
    bg.x = this.canvasWidth / 2;
    bg.y = this.canvasHeight / 2;
    let sx = this.canvasWidth / bg.width;
    let sy = this.canvasHeight / bg.height;
    let s = Math.max(sx, sy);
    bg.setScaleXY(s);
    this.renderArr.push(bg);


    const bgItem = new MySprite();
    bgItem.init(this.images.get(this.data.contentObj.bgItem.url));
    bgItem.x = this.canvasWidth / 2;
    bgItem.y = this.canvasHeight / 10 * 5.5;

    const maxW = this.canvasWidth * 0.9;
    const maxH = this.canvasHeight * 0.8;
    sx = maxW / bgItem.width;
    sy = maxH / bgItem.height;
    s = Math.min(sx, sy);
    bgItem.setScaleXY(s);
    bgItem.setShadow(5, 5, 10);
    // bgItem.setShadow(15, 15, 20, 'rgba(0,0,0,0.5)');
    this.bg = bgItem;


    const edge = 20;
    const shapeRect = new ShapeRect();
    shapeRect.init();
    shapeRect.setSize(bgItem.width * bgItem.scaleX + edge * this.mapScale, bgItem.height * bgItem.scaleY + edge * this.mapScale);
    shapeRect.fillColor = '#ffffff';
    shapeRect.setShadow(0, 5, 10);
    shapeRect.x = bgItem.x;
    shapeRect.y = bgItem.y;
    this.bgRect = shapeRect;

    this.renderArr.push(shapeRect);


    bgItem.x = 0;
    bgItem.y = 0;
    shapeRect.addChild(bgItem);
    // this.renderArr.push(bgItem);


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

  }

  sendServerEvent(key, data = null) {
    console.log('data: ', data);
    const c = (<any> window).courseware;
    c.sendEvent(key, data);
  }

  totalTeacherPage = 1;

  addTeacherPageData(data) {
    let hasFlag = false;
    for (let i = 0; i < this.scoreDataArr.length; i++) {
      if (data.user.uuid == this.scoreDataArr[i].user.uuid) {
        data.updateTime = new Date().getTime();
        this.scoreDataArr[i] = data;
        hasFlag = true;
        break;
      }
    }
    if (!hasFlag) {
      this.scoreDataArr.push(data);
    }

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

      if (a.score == b.score) {
        return a.updateTime - b.updateTime;
      } else {
        return b.score - a.score;
      }

    });
    const pageListNum = 5;
    this.totalTeacherPage = Math.ceil(this.scoreDataArr.length / pageListNum);
    this.refreshTeacherPage();
    console.log('this.scoreDataArr.length:', this.scoreDataArr.length);
  }

  refreshTeacherPage() {
    const pageNum = 5;
    const startIndex = (this.curTeacherPage - 1) * pageNum;
    const dataArr = this.scoreDataArr.slice(startIndex, startIndex + pageNum);
    for (let i = 0; i < this.teacherPageListArr.length; i++) {
      const list = this.teacherPageListArr[i];
      if (dataArr[i]) {
        list.num.visible = true;
        list.name.visible = true;
        list.score.visible = true;
        list.finish.visible = dataArr[i].finish;
        list.num.text = startIndex + i + 1;
        list.name.text = dataArr[i].user.nick_name.toString();
        list.score.text = dataArr[i].score.toString();
      } else {
        list.num.visible = false;
        list.name.visible = false;
        list.score.visible = false;
        list.finish.visible = false;
      }
    }
    this.teacherPageLabel.text = this.curTeacherPage + ' / ' + this.totalTeacherPage;
  }

  changePage(value) {
    if (value < 0 && this.curTeacherPage > 1) {
      this.curTeacherPage--;
      this.refreshTeacherPage();
    }

    if (value > 0 && this.curTeacherPage < this.totalTeacherPage) {
      this.curTeacherPage++;
      this.refreshTeacherPage();
    }
  }

  addServerListener() {
    const c = (<any> window).courseware;
    const that = this;
    if (this.teachFlag) {
      c.onEvent('start_game', function(data, next) {
        console.log('show teacher page');
        that.isGaming = true;
        that.teacherPage.visible = true;
        next();
      });
      c.onEvent('score_data', function(data, next) {
        that.addTeacherPageData(data);
        next();
      });
    } else {
      c.onEvent('start_game', function(data, next) {


        that.isGaming = true;

        that.showAudio();

        next();
      });
      // todo 学生的游戏开始
    }
  }

  titleLabelClicked() {
    this.showAudio();
  }


  // todo
  mapDown(event) {

    if (this.gameEndFlag) {
      return;
    }

    (window as any).test = this;



    // 如果游戏未开始，并且是老师身份，则点击时开始游戏
    if (!this.isGaming && this.teachFlag && this.checkClickTarget(this.startBtn)) {
      this.sendServerEvent('start_game', {startFlag: true});
      return;
    }
    if (!this.isGaming) {
      return;
    }


    if (this.teacherPage.visible) {
      if (this.checkClickTarget(this.arrowL)) {
        this.changePage(-1);
      } else if (this.checkClickTarget(this.arrowR)) {
        this.changePage(1);
      }
      return;
    }
    if (this.teachFlag) {
      return;
    }


    if (!this.canTouch) {
      return;
    }

    this.canTouch = false;


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

    if (this.checkClickTarget(this.titleLabel)) {
      this.titleLabelClicked();
      return;
    }
    this.clickWrong();
  }


  mapMove(event) {

  }


  mapUp(event) {


  }


  clickHotZone(index) {

    if (this.clickedSuccessArr.indexOf(index) != -1) {
      console.log('return');
      this.canTouch = true;
      return;
    }

    this.clickedSuccessArr.push(index);

    const data = this.picArr[this.curPageIndex];
    const options = data.options;
    if (options[index] && options[index].checked) {
      console.log('right');
      this.showFrame(index);
    } else {
      console.log('wrong');
      this.clickWrong();
    }
  }

  clickWrong() {


    this.playAudio('wrong', true);
    shake(this.bgRect, 0.5, () => {
      this.canTouch = true;
    });

  }

  showFrame(index) {

    this.playAudio('right', true);

    const light = this.light;
    light.setScaleXY(0);
    light.alpha = 0;
    light.visible = true;

    const hotZone = this.hotZoneArr[index];
    const px = hotZone.x + hotZone.width / 2;
    const py = hotZone.y + hotZone.height / 2;

    light.x = px;
    light.y = py;

    const edge = 48;

    light.setSize(hotZone.width, hotZone.height);

    tweenChange(light, {
      scaleX: 1, // hotZone.width / (light.width - edge * 2),
      scaleY: 1, // hotZone.height / (light.height - edge * 2),
      alpha: 1
    }, 0.5, () => {

      setTimeout(() => {

        hideItem(light, 0.3, () => {

        }, TWEEN.Easing.Quadratic.In);
      }, 200);


    }, TWEEN.Easing.Quadratic.Out);

    setTimeout(() => {

      this.playAudio('star', true);
      showPopParticle(this.images.get('star'), {x: px, y: py},
        this.particleLayer, 20, 50 * this.mapScale, 100 * this.mapScale, 1);
    }, 400);

    setTimeout(() => {
      this.showShadow(hotZone);
    }, 1000);

  }


  showShadow(hotZone) {

    const shadow = new MySprite();
    shadow.init(this.images.get('shadow'));
    shadow.alpha = 0;
    shadow.x = hotZone.x + hotZone.width / 2;
    shadow.y = hotZone.y + hotZone.height / 2;
    shadow.childDepandAlpha = true;
    this.renderArr.push(shadow);

    const lineRect = new LineRect();
    lineRect.init();
    lineRect.lineWidth = 2 * this.mapScale;
    lineRect.lineColor = '#c2ff39';
    lineRect.setSize(hotZone.width - lineRect.lineWidth, hotZone.height - lineRect.lineWidth);
    shadow.addChild(lineRect);


    const sx = hotZone.width / (shadow.width - 360);
    const sy = hotZone.height / (shadow.height - 360);
    shadow.scaleX = sx;
    shadow.scaleY = sy;

    lineRect.scaleX = 1 / sx;
    lineRect.scaleY = 1 / sy;


    showItem(shadow, 0.5, () => {
      this.checkGameEnd();
    });
    this.shadowArr.push(shadow);
  }


  checkGameEnd() {

    this.answerCurrent++;

    if (this.answerCurrent < this.answerTarget) {
      this.canTouch = true;
      return;
    }

    this.setServerPicArr(null);

    this.curPageIndex++;
    this.refreshPageLabel();






    if (this.curPageIndex >= this.picArr.length) {
      this.gameEnd();
      return;
    }

    setTimeout(() => {


      // if (this.curPageIndex >= this.picArr.length) {
      //   this.gameEnd();
      //   return;
      // }

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

        const shadow = this.shadowArr[i];
        hideItem(shadow, 0.2, () => {
          removeItemFromArr(this.renderArr, shadow);
        });
      }
      this.shadowArr = [];

      // this.refreshPageLabel();
      this.refreshTitleLabel(true);
      this.refreshAnswerNum();


      this.canTouch = true;
    }, 2500);
  }


  refreshAnswerNum() {


    this.answerCurrent = 0;
    this.answerTarget = 0;

    this.clickedSuccessArr = [];

    const data = this.picArr[this.curPageIndex];
    const options = data.options;

    console.log('options: ', options);

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

      // console.log('options:', options[i]);
      if (options[i].checked) {
        this.answerTarget++;
      }
    }
  }


  gameEnd() {

    this.playAudio('finish', true);
    this.showEndPetal();

    setTimeout(() => {
      this.showPetalFlag = false;
    }, 5000);

    this.gameEndFlag = true;
  }

  update() {
    this.animationId = window.requestAnimationFrame(this.update.bind(this));
    // 清除画布内容
    this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
    TWEEN.update();
    this.updateArr(this.renderArr);
    this.updateItem(this.particleLayer);
    this.updateArr(this.endPageArr);
    if (!this.isGaming) {
      this.updateArr(this.coverPageArr);
    }
    if (this.isGaming && this.teachFlag) {
      this.updateArr(this.teacherPageArr);
    }
  }

  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.imgArr = [];
    // const arr = this.data.contentObj.imgItemArr;
    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]));
      // const img = {pic_url: data.pic_url};

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


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

  stopEndPetal() {
    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();
    }, 100);

  }


  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 = 0.5 + Math.random() * 2.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();
      }
      console.log('mouse down');
      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.crossOrigin = "anonymous";
      img.onload = () => resolve(img);
      img.onerror = reject;
      img.src = url;
    });
  }

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

      resolve();

    });
  }


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

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

}
