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

import {
  Label,
  MySprite, 
  ShapeRect,
  tweenChange,
  removeItemFromArr,
  showPopParticle,
  rotateItem,
  randomSortByArr,
  hideItem,
  moveItem
} from './Unit';
import {res, resAudio} from './resources';

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

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

import {setFontSize,
  getRandomItemFromArr} from './MyUtil'


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

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

  // 数据
  data;

  ctx;

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

  bgRenderArr;

  renderArr;

  /**青蛙渲染数组 */
  renderFrogArr;

  starRenderArr;

  endRenderArr;

  mapScale = 1;

  canvasLeft;
  canvasTop;

  saveKey = 'DF_L223';

  /**背景图片 */
  bg;

  btnStart;

  btnRestart;

  canTouch = true;

  frogCanTouch = false;

  /**玩游戏状态 */
  playStatus = false;

  /**游戏结束标识*/
  playEnd = false;

  /**左上角水波*/
  leftWave;

  /**右上角水波*/
  rightWave;

  /**大荷叶 */
  bigLotusLeaf;

  /**青蛙 */
  frog;

  //小荷叶坐标数组
  leafMapArr = [];

  //小荷叶
  smallLotusLeafs = [];

  //小荷叶临时数组
  tempSmallLotusLeafs = [];

  /**屏幕星星临时数组*/
  tempStarArr = [];


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


  ngOnInit() {

    this.data = {};

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

      if (data && typeof data == 'object') {
        this.data = data;
      }
      // console.log('data:' , data);

      // 初始化 各事件监听
      this.initListener();

      // 若无数据 则为预览模式 需要填充一些默认数据用来显示
      this.initDefaultData();

      // 初始化 音频资源
      this.initAudio();
      // 初始化 图片资源
      this.initImg();
      // 开始预加载资源
      this.load();

    }, this.saveKey);

  }

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


  load() {

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


  init() {

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

  initCtx() {
    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;


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

    window['curCtx'] = this.ctx;
  }






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

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







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

  pauseAudio(key, callback = null){

    const audio = this.audioObj[key];
    if (audio) {

      if (callback) {
        audio.onended = () => {
          callback();
        };
      }
      audio.pause();
    }
  }


  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) => {
        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() {

    if(!this.data.exercises){

      this.data.exercises = [];

      let exercises = {contents:[]};

      this.data.exercises.push(exercises);

      for(let i = 0; i < 5; ++ i){

        let contentItem;

        if(i % 2 == 0){
          contentItem = this.getDefaultContentItem('Hello', null);
        }
        else if(i % 3 == 0){
          contentItem = this.getDefaultContentItem('World', null);
        }
        else{
          contentItem = this.getDefaultContentItem('Lion', null);
        }
        console.log(contentItem);
        exercises.contents.push(contentItem);
   
      }
    }

    if(this.data.exercises[0].contents.length == 0){
      
      for(let i = 0; i < 5; ++ i){

        let contentItem;

        if(i % 2 == 0){
          contentItem = this.getDefaultContentItem('Hello', null);
        }
        else if(i % 3 == 0){
          contentItem = this.getDefaultContentItem('World', null);
        }
        else{
          contentItem = this.getDefaultContentItem('Lion', null);
        }
        console.log(contentItem);

        this.data.exercises[0].contents.push(contentItem);
   
      }
    }
  }

  /**
   * 
   * @param text 
   * @param pic_url 
   */
  getDefaultContentItem(text, pic_url){
    let content = {
      val:text,
      pic_url:pic_url,
      audio_url:this.rawAudios.get('click')
    }

    return content;
  }


  /**
   * 添加预加载图片
   */
  initImg() {

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

      let exercises = this.data.exercises[i];

      for(let j = 0; j < exercises.contents.length; ++ j){
        let content = exercises.contents[j];

        this.addUrlToImages(content.pic_url);
      }
    }

  }

  /**
   * 添加预加载音频
   */
  initAudio() {

    this.addUrlToAudioObj('click', this.rawAudios.get('click'));

    this.addUrlToAudioObj('croak', this.rawAudios.get('croak'));

    this.addUrlToAudioObj('handclap', this.rawAudios.get('handclap'));

    this.addUrlToAudioObj('jump', this.rawAudios.get('jump'));

    this.addUrlToAudioObj('showContent', this.rawAudios.get('showContent'));

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

      let exercises = this.data.exercises[i];

      for(let j = 0; j < exercises.contents.length; ++ j){

        let content = exercises.contents[j];

        this.addUrlToAudioObj(content.audio_url);
      }
    }

  }



  /**
   * 初始化数据
   */
  initData() {

    const sx = this.canvasWidth / this.canvasBaseW;
    const sy = this.canvasHeight / this.canvasBaseH;
    const s = Math.min(sx, sy);
    this.mapScale = s;

    // this.mapScale = sx;
    // this.mapScale = sy;

    this.bgRenderArr = [];

    this.renderArr = [];

    this.renderFrogArr = [];

    this.starRenderArr = [];

    this.endRenderArr = [];

    this.leftWave = {};

    this.rightWave = {};

    this.bigLotusLeaf = {};

    this.frog = {};

    this.btnRestart = {};

    this.btnStart = {};

    this.leafMapArr = [];

    this.smallLotusLeafs = [];

    this.tempSmallLotusLeafs = [];

    this.playStatus = false;

    this.tempStarArr = [];

    this.playEnd = false;
  }



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


    this.initPic();

    this.initBottomPart();

    this.initLeftWavesPic();

    this.initRightWavesPic();

    this.initBigLotusLeaf();

    this.initFrogPic();

    this.initSmallLotusLeaf();
  }

  initBottomPart() {

    
    const btnStart = new MySprite();
    btnStart.init(this.images.get('start'));
    btnStart.setScaleXY(this.mapScale);
    btnStart.x = this.canvasWidth - 50 * this.mapScale - btnStart.getBoundingBox().width / 2;
    btnStart.y = this.canvasHeight - 100 * this.mapScale;

    this.renderArr.push(btnStart);

    this.btnStart.sprite = btnStart;

    const btnRestart = new MySprite();
    btnRestart.init(this.images.get('restart'));
    btnRestart.setScaleXY(this.mapScale);
    btnRestart.x = this.canvasWidth + btnRestart.getBoundingBox().width / 2;
    btnRestart.y = btnStart.y;

    this.renderArr.push(btnRestart);

    this.btnRestart.sprite = btnRestart;
    this.btnRestart.showX = btnStart.x;
    this.btnRestart.showY = btnStart.y;
    this.btnRestart.initX = btnRestart.x;
    this.btnRestart.initY = btnRestart.y;

  }

  

  initPic() {


    const bg_pic = new MySprite();
    bg_pic.init(this.images.get("bg"));
    bg_pic.x = this.canvasWidth / 2;
    bg_pic.y = this.canvasHeight / 2;
    bg_pic.setScaleXY(Math.max(this.canvasWidth / bg_pic.width, this.canvasHeight / bg_pic.height));
    bg_pic.childDepandAlpha = false;
    
    this.bgRenderArr.push(bg_pic);

    const bg = new ShapeRect();
    bg.fillColor = '#75d100';
    bg.alpha = 0;
    bg.setSize(this.canvasWidth, this.canvasHeight);
    this.starRenderArr.push(bg); 
    this.bg = bg;


  }

  /**
   * 获得小水波组合
   */
  getSmallWaveGropPic(){
    const wave1 = new MySprite();
    wave1.init(this.images.get("s_wave"));   
    wave1.setScaleXY(0.3 * this.mapScale);
    wave1.x = wave1.width / 2;
    wave1.y = wave1.height  / 2;

    const wave2 = new MySprite();
    wave2.init(this.images.get("s_wave"));   
    wave2.setScaleXY(1 * this.mapScale);
    wave2.alpha = 0;
    wave2.x = wave1.x;
    wave2.y = wave1.y;

    const waveBg = new ShapeRect();
    waveBg.fillColor = '#75d100';
    waveBg.alpha = 0;
    waveBg.setSize(wave1.width, wave1.height);
    waveBg.addChild(wave1);
    waveBg.addChild(wave2);
    waveBg.x = Math.random() * this.canvasWidth;

    waveBg.y = Math.random() * this.canvasHeight;

    this.bgRenderArr.push(waveBg);

    

    const showWave1 = () =>{
      tweenChange(wave1, {alpha:0, scaleX:this.mapScale, scaleY:this.mapScale}, 0.6, null, null, (a, b)=>{
       if(b >= 0.5/0.6){
        showWave2();
       }
      });
    }

    const showWave2 = () => {
      tweenChange(wave1, {alpha:0, scaleX:this.mapScale * 1.3, scaleY:this.mapScale * 1.3}, 0.5, ()=>{

        //移除小水珠
        removeItemFromArr(this.bgRenderArr, waveBg);
      });
    };

    showWave1();

    return {waveBg:waveBg, wave1:wave1, wave2:wave2};
  } 

  /**
   * 初始左上角水波图标
   */
  initLeftWavesPic(){

    const l_wave = new MySprite();
    l_wave.init(this.images.get("l_wave"));
    l_wave.setScaleXY(this.mapScale);
    l_wave.x = -l_wave.getBoundingBox().width / 2;
    l_wave.y = -l_wave.getBoundingBox().height / 2;
    this.renderArr.push(l_wave);

    this.leftWave.sprite = l_wave;
    //设置初始位置
    this.leftWave.initX = l_wave.x;
    this.leftWave.initY = l_wave.y;

    //设置移动到位置
    this.leftWave.toX = l_wave.getBoundingBox().width / 2;
    this.leftWave.toY = l_wave.getBoundingBox().height / 2;

    this.moveWave(this.leftWave, 3, 2000);
  }

/**
   * 初始右上角水波图标
   */
  initRightWavesPic(){


    const r_wave = new MySprite();
    r_wave.setScaleXY(this.mapScale);
    r_wave.init(this.images.get("r_wave"));
    r_wave.x = this.canvasWidth + r_wave.getBoundingBox().width / 2;
    r_wave.y = - r_wave.getBoundingBox().height / 2;
    this.renderArr.push(r_wave);
    this.rightWave.sprite = r_wave;
    //设置移动到位置
    this.rightWave.toX = this.canvasWidth - r_wave.getBoundingBox().width / 2;
    this.rightWave.toY = r_wave.getBoundingBox().height / 2;

    //设置初始位置
    this.rightWave.initX = r_wave.x;
    this.rightWave.initY = r_wave.y;

    this.moveWave(this.rightWave, 3, 2000);
  }

  /**
   * 初始化大荷叶
   */
  initBigLotusLeaf(){

    //荷叶
    const lotusLeaf = new MySprite();
    lotusLeaf.setScaleXY(this.mapScale);
    lotusLeaf.init(this.images.get("b_lotus_leaf"));
    lotusLeaf.x = this.canvasWidth + lotusLeaf.getBoundingBox().width / 2;
    lotusLeaf.y = this.canvasHeight + lotusLeaf.getBoundingBox().height / 2;
    
    this.bigLotusLeaf.lotusLeaf = lotusLeaf;

    let initX = this.canvasWidth - lotusLeaf.getBoundingBox().width / 2 - 150 * this.mapScale;
    this.bigLotusLeaf.initX = initX;
    let initY = this.canvasHeight - lotusLeaf.getBoundingBox().height / 2 + 80 * this.mapScale;
    this.bigLotusLeaf.initY = initY;

    //水波
    const leafWave = new MySprite();
    leafWave.setScaleXY(this.mapScale * 0.6);
    leafWave.init(this.images.get("b_leaf_wave"));
    leafWave.x = initX;
    leafWave.y = initY;
    leafWave.visible = false;
    this.renderArr.push(leafWave);
    this.bigLotusLeaf.leafWave = leafWave;

    

    //影子
    const shadow = new MySprite();
    shadow.setScaleXY(this.mapScale);
    shadow.init(this.images.get("b_shadow"));
    shadow.x = initX;
    shadow.y = initY;
    shadow.visible = false;
    this.renderArr.push(shadow);
    this.bigLotusLeaf.shadow = shadow;

    //添加荷叶到渲染数组
    this.renderArr.push(lotusLeaf);
  }



  /**
   * 初始青蛙图片
   */
  initFrogPic(){

    if(!this.frog.standbys){
      this.frog.standbys = [];
    }

    let frogWidth = 0;

    let frogHeight = 0;

    //初始化待机图片
    const initStandbyPic = (index) =>{
      const frogStandby = new MySprite();
      frogStandby.setScaleXY(this.mapScale > 1 ? 1 : this.mapScale);
      frogStandby.init(this.images.get("standby-" + index));

      frogWidth = frogStandby.getBoundingBox().width;
      frogHeight = frogStandby.getBoundingBox().height;

      //初始不可见
      frogStandby.visible = false;

      frogStandby.x = frogWidth/2;
      frogStandby.y = frogHeight/2;
      this.frog.standbys.push(frogStandby);
    };

    //初始青待机图片
    for(let i = 0; i < 28; ++ i){

      let index = String(i + 1);
      if(i < 9){
        index = "0" + (i + 1);
      }
      //console.log(index);
      initStandbyPic(index);
    }

    //青蛙初始位置
    this.frog.initX = this.canvasWidth + frogWidth;
    this.frog.initY = this.canvasHeight;

    this.frog.width = frogWidth;
    this.frog.height = frogHeight;

    //青蛙背景
    const frogBg = new ShapeRect();
    frogBg.setSize(frogWidth, frogHeight);
    frogBg.fillColor ="#696969";
    frogBg.alpha= 0;
    frogBg.x = this.frog.initX;
    frogBg.y = this.frog.initY;
    this.frog.bg = frogBg;
    this.renderFrogArr.push(frogBg);

    //将待机图片添加背景图片
    for(let i = 0; i < this.frog.standbys.length; ++ i){
      frogBg.addChild(this.frog.standbys[i]);
    }

    //青蛙跳起
    {
      const jumpedUp = new MySprite();
      jumpedUp.setScaleXY(this.mapScale > 1 ? 1 : this.mapScale);
      jumpedUp.init(this.images.get("jumped_up"));

      //初始不可见
      jumpedUp.visible = true;

      jumpedUp.x = jumpedUp.getBoundingBox().width / 2;
      jumpedUp.y = jumpedUp.getBoundingBox().height / 2;

      frogBg.addChild(jumpedUp);

      this.frog.jumpedUp = jumpedUp;
    }
    
    //播放青蛙待机动画
    this.animation(this.frog, this.frog.standbys, 0, 40);
  }


  /**
   * 初始化小荷叶
   */
  initSmallLotusLeaf(){

    //荷叶宽度
    let width = 340 * this.mapScale;

    //荷叶高度
    let height = 209 * this.mapScale;

    //计算所有荷叶坐标
    
    //荷叶1
    this.leafMapArr.push({x: 160 * this.mapScale +  width /2, y: 80 * this.mapScale + height / 2});

    //荷叶2
    this.leafMapArr.push({x: this.canvasWidth/2 + 40 * this.mapScale +  width /2, y: 20 * this.mapScale + height / 2});

    //荷叶3
    this.leafMapArr.push({x: 30 * this.mapScale +  width /2, y: this.canvasHeight/2  + height / 2});

    //荷叶4
    this.leafMapArr.push({x:  this.canvasWidth/2 - 210 * this.mapScale +  width /2, y: this.canvasHeight/2 - 140 * this.mapScale + height / 2});

    //荷叶5
    this.leafMapArr.push({x:  this.canvasWidth - 30 * this.mapScale -  width /2, y: this.canvasHeight/2 - 180 * this.mapScale + height / 2});

    console.log('leafMapArr', this.leafMapArr);

    const initLotusLeafPic = (content, x, y) =>{

      let lotusLeafObj = {leaf:null, droplet:null, hl:null, conText:null, conPic:null, shadow: null, canVoice: false, audioUrl:content.audio_url};

      const lotusLeaf = new MySprite();
      lotusLeaf.setScaleXY(this.mapScale);
      lotusLeaf.init(this.images.get("s_lotus_leaf"));

      lotusLeaf.x = x;
      lotusLeaf.y = y;
      this.renderArr.push(lotusLeaf);
      lotusLeafObj.leaf = lotusLeaf;
      
      
      //高亮荷叶
      const hightLightLotusLeaf = new MySprite();
      hightLightLotusLeaf.setScaleXY(this.mapScale);
      hightLightLotusLeaf.init(this.images.get("s_lotus_leaf_light"));
      hightLightLotusLeaf.alpha = 0;
      hightLightLotusLeaf.x = x;
      hightLightLotusLeaf.y = y;
      this.renderArr.push(hightLightLotusLeaf);
      lotusLeafObj.hl = hightLightLotusLeaf;

      //设置内容
      this.setContent(content, lotusLeaf, hightLightLotusLeaf, lotusLeafObj);

      //小珠
      const droplet = new MySprite();
      droplet.setScaleXY(0.1);
      droplet.init(this.images.get("droplet"));
      droplet.alpha = 0;
      droplet.x = x;
      droplet.y = y;
      this.renderArr.push(droplet);
      lotusLeafObj.droplet = droplet;


      //阴影
      const shadow = new MySprite();
      shadow.setScaleXY(this.mapScale);
      shadow.init(this.images.get("s_shadow"));

      shadow.x = lotusLeaf.x;
      shadow.y = lotusLeaf.y;
      this.renderArr.push(shadow);
      lotusLeafObj.shadow = shadow;

      this.smallLotusLeafs.push(lotusLeafObj);
    };

    //取练习题
    let exercises = this.data.exercises[0];

    //打乱数组
    let contents = randomSortByArr(exercises.contents);

    console.log('random contents', contents);

    //初始小荷叶
    for(let i = 0; i < contents.length; ++ i){

      let content = contents[i];

      initLotusLeafPic(content, this.leafMapArr[i].x, this.leafMapArr[i].y);
    }

    this.tempSmallLotusLeafs = [...this.smallLotusLeafs];

  }

  /**
   * 设置内容
   */
  setContent(content, parItem, parItem2, lotusLeafObj){

    //图片存在，则渲染图片
    if(content.pic_url){
      
      const content_pic = new MySprite();
      content_pic.init(this.images.get(content.pic_url));

      let w = content_pic.width;

      let h = content_pic.height;

      let d = Math.sqrt( w * w + h * h);

      content_pic.setScaleXY((parItem.height - 22 * this.mapScale) / d);

      content_pic.alpha = 0;

      content_pic.x = 0;
      content_pic.y = -10 * this.mapScale; 
      parItem.addChild(content_pic);
      parItem2.addChild(content_pic);
     
      lotusLeafObj.conPic = content_pic;
    }
    else{
      let content_val = new Label();
      content_val.text = content.val;
      content_val.textAlign='middle';
      content_val.fontSize = 120;
      content_val.fontName = "BRLNSDB";
      content_val.fontColor = "#FFFFFF";
      content_val.alpha = 0;

      content_val.refreshSize();

      content_val.setOutline(5, "#006400");
     
      setFontSize(parItem.height - 40 * this.mapScale, content_val);

      content_val.refreshSize();

      content_val.x = - content_val.getBoundingBox().width/2;
      content_val.y = -20 * this.mapScale;


      lotusLeafObj.conText = content_val;

      parItem.addChild(content_val);
      parItem2.addChild(content_val);
    }

    parItem2.childDepandAlpha = false;
    
  }

  /**
   * 移动水波
   * @param wave 
   * @param time 
   * @param intervalTime 
   */
  moveWave(wave, time:number, intervalTime:number){
    //从初始位置移动到指定位置并进行透明度变化
    tweenChange(wave.sprite, {x:wave.toX, y:wave.toY, alpha:0}, time, ()=>{

      //回到初始位置
      wave.sprite.x = wave.initX;
      wave.sprite.y = wave.initY;

      //回到初始透明度
      wave.sprite.alpha = 1;

      
      setTimeout(() => {
        this.moveWave(wave, time, intervalTime);
      }, intervalTime);
      
    });
  }

  /**
   * 播放序列针动画
   * @param parItem 
   * @param arr 图片数组
   * @param nextIndex 下一图片顺序
   * @param intervalTime 间隔时间
   */
  animation(parItem, arr, nextIndex : number, intervalTime : number){

    if(!parItem){
      return;
    }

    if(!arr || arr.length == 0){
      return;
    }

    let tNextIndex = nextIndex;

    //如果相等，则表示一轮播放结束，将播放顺序重置为0
    if(nextIndex == arr.length){
      tNextIndex = 0;
    }

    //暂停动画
    if(parItem.animationStop){

      //隐藏上一张图
      if(nextIndex > 0){
        arr[nextIndex - 1].visible = false;
      }
      else if(nextIndex == 0){
        arr[nextIndex].visible = false;
      }

      return;
    }

    //console.log('nextIndex', tNextIndex);

    //隐藏上一张图
    if(nextIndex > 0){
      arr[nextIndex - 1].visible = false;
    }

    arr[tNextIndex].visible = true;

    setTimeout(() => {

      let nextIndex = tNextIndex + 1;

      this.animation(parItem, arr, nextIndex, intervalTime);

    }, intervalTime);
  }

  mapDown(event) {

    if (!this.canTouch) {
      return;
    }

    if(this.checkClickTarget(this.btnStart.sprite)){

      this.playAudio('click');
      this.btnStart.keyDown = true;
      this.btnStart.sprite.setScaleXY(this.mapScale * 1.3);
      return;
    }

    if ( this.checkClickTarget(this.btnRestart.sprite)) {
      this.playAudio('click');
      this.btnRestart.keyDown = true;
      this.btnRestart.sprite.setScaleXY(this.mapScale * 1.3);
      return;
    }

    
    if(this.frogCanTouch){

      if(this.checkClickTarget(this.frog.bg)){

        this.frogCanTouch = false;

       this.jumpToSmallLotusLeaf();
      }

    }

    //判断是否点击了荷叶上的内容
    for(let i = 0; i < this.smallLotusLeafs.length; ++ i){

      if(this.checkClickTarget(this.smallLotusLeafs[i].leaf)){
        //可以发音，则点击发音
        if(this.smallLotusLeafs[i].canVoice){
          
          //停止所有的音效
          for(let j = 0; j < this.smallLotusLeafs.length; ++ j){
            
            let audio = this.audioObj[this.smallLotusLeafs[j].audioUrl];
            audio.currentTime = 0;
            audio.pause();
          }

          this.playAudio(this.smallLotusLeafs[i].audioUrl);
        }
      }
    }


  }

  mapMove(event) {

  }

  mapUp(event) {

    if(!this.canTouch){
      return;
    }

    if(this.checkClickTarget(this.btnStart.sprite)){

      //按下松开
      if(this.btnStart.keyDown = true){

        this.btnStart.keyDown = false;

        let toX = this.btnStart.sprite.getBoundingBox().width + this.btnStart.sprite.x;

        //向左移出
        tweenChange(this.btnStart.sprite, {x : toX}, 0.3, ()=>{

          //恢复原来大小写
          this.btnStart.sprite.setScaleXY(this.mapScale);

          //开始游戏
          this.playGame();
        });

        
      }
    }

    if(this.checkClickTarget(this.btnRestart.sprite)){

      //按下松开
      if(this.btnRestart.keyDown = true){

        this.btnRestart.keyDown = false;

        let toX = this.btnRestart.initX;

        //向左移出
        tweenChange(this.btnRestart.sprite, {x : toX}, 0.3, ()=>{

          //恢复原来大小写
          this.btnRestart.sprite.setScaleXY(this.mapScale);

          //开始游戏
          this.restartGame();
        });

        
      }
    }
    
  }



  update() {

    // ----------------------------------------------------------
    this.animationId = window.requestAnimationFrame(this.update.bind(this));
    // 清除画布内容
    this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
    // tween 更新动画
    TWEEN.update();
    // ----------------------------------------------------------

    this.updateArr(this.bgRenderArr);

    this.updateArr(this.renderArr);

    this.updateArr(this.renderFrogArr);

    this.updateArr(this.starRenderArr);

    this.updateArr(this.endRenderArr);
  }

  /**
   * 显示小水波
   */
  showSmallWaveGrop(){

    //未开始游戏，直接返回
    if(!this.playStatus){
      return;
    }

    //产生水波个数
    let count = Math.ceil(Math.random() * 2) + 3;


    for(let i = 0; i < count; ++ i){

      this.getSmallWaveGropPic();
      
    }

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

  /**
   * 显示屏幕小星星
   */
  showStar(){
    if(!this.playStatus){
      return;
    }

    const star = this.getStar();
    this.starRenderArr.push(star);
    this.tempStarArr.push(star);

    hideItem(star, 2, () => {
      removeItemFromArr(this.starRenderArr, star);
      removeItemFromArr(this.tempStarArr, star);
    });

    rotateItem(star, star['tr'], star['time']);

    setTimeout(() => {

      if(this.tempStarArr.length < 10){
        this.showStar();
      }
      
    }, 500);
  }


  getStar() {

    const star = new MySprite(this.ctx);

    star.init(this.images.get('star'));

    const randomS = (Math.random() * 0.5 + 0.3) * this.mapScale;
    star.setScaleXY(randomS);

    const randomR = Math.random() * 360;
    star.rotation = randomR;

    const randomX = Math.random() * this.canvasWidth;
    star.x = randomX;
    star.y = Math.random() * this.canvasHeight;

    const randomT = 2 + Math.random() * 5;
    star['time'] = randomT;

    let randomTR = 360 * Math.random(); // - 180;
    if (Math.random() < 0.5) { randomTR *= -1; }
    star['tr'] = randomTR;

    return star;
  }

  /**
   * 开始游戏
   */
  playGame(){

    this.playStatus = true;

    //显示小水波
    this.showSmallWaveGrop();

    //显示小星星
    this.showStar();

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

      let lotusLeaf = this.smallLotusLeafs[i];

      //显示小水珠
      //lotusLeaf.droplet.alpha = 1;    

      //显示内容
      let content;

      if(lotusLeaf.conPic){
        content = lotusLeaf.conPic;
      }
      else{
        content = lotusLeaf.conText;
      }

      //显示内容
      tweenChange(content, {alpha:1}, 0.5, ()=>{

        //隐藏小水珠
        //lotusLeaf.droplet.alpha = 0;
   
      });

      //高亮显示荷叶
      tweenChange(lotusLeaf.hl, {alpha:1}, 0.5, ()=>{

        //3秒后恢复原状
        setTimeout(() => {

          tweenChange(lotusLeaf.hl, {alpha:0}, 0.5, ()=>{
            //显示水珠
            //lotusLeaf.droplet.alpha = 1;

            
            
          });

          //隐藏内容
          tweenChange(content, {alpha:0}, 0.5, ()=>{
          
          });

          //最后一次，显示大荷叶
          if(i == this.smallLotusLeafs.length - 1){
            //显示大荷叶
            showBigLotus();
          }

          //显示小水珠
          tweenChange(lotusLeaf.droplet, {alpha :1, scaleX : this.mapScale, scaleY : this.mapScale}, 0.5)
            
        }, 3000);
      });
    }

    //显示荷叶
    const showBigLotus = () =>{

      tweenChange(this.bigLotusLeaf.lotusLeaf, {x: this.bigLotusLeaf.initX, y:this.bigLotusLeaf.initY}, 0.5, ()=>{
        
        this.toggleBigLotus();

        this.shakeWave();

        //跳转到大荷叶
        this.jumpToBigLotusLeaf();

      });

    }
    
  }

  /**
   * 跳转到大荷叶上
   */
  jumpToBigLotusLeaf(){

    //设置初始位置
    this.frog.bg.x = this.frog.initX;

    this.frog.bg.y = this.frog.initY;

    //青蛙跳到大荷叶上
    this.frog.animationStop = true;

    this.frog.jumpedUp.visible = true;

    //计算青蛙新位置
    let toX = this.bigLotusLeaf.lotusLeaf.x - this.frog.width / 2;
    let toY = this.bigLotusLeaf.lotusLeaf.y - this.frog.height + 50 * this.mapScale;

    this.frog.bigLeafX = toX;
    this.frog.bigLeafY = toY;

    //跳到大荷叶上
    this.frogJump(toX, toY, 0.5, ()=>{

      this.playAudio('croak');

      this.frogCanTouch = true;

      //播放青蛙待机动画
      this.animation(this.frog, this.frog.standbys, 0, 80);
    });

    
  }

  /**
   * 跳到小荷叶上
   */
  jumpToSmallLotusLeaf(){

    if(this.tempSmallLotusLeafs.length == 0){
      return;
    }
    //获取随机荷叶
    let lotusLeaf = getRandomItemFromArr(this.tempSmallLotusLeafs);

    removeItemFromArr(this.tempSmallLotusLeafs, lotusLeaf);

    //console.log('lotusLeaf', lotusLeaf);

    let toX = lotusLeaf.leaf.x - this.frog.width / 2;
    let toY = lotusLeaf.leaf.y - this.frog.height + 50 * this.mapScale;

    this.playAudio('jump');

    this.frogJump(toX, toY, 0.3,()=>{

      //显示星星
      this.showParticle(lotusLeaf.leaf);

      //水珠消失
      lotusLeaf.droplet.alpha = 0;

      //显示高亮图片
      lotusLeaf.hl.alpha = 1;

      this.playAudio('showContent');

      if(lotusLeaf.conPic){
        lotusLeaf.conPic.alpha = 1;
      }
      else{
        lotusLeaf.conText.alpha = 1;
      }

      lotusLeaf.canVoice = true;

      //荷叶放大
      tweenChange(lotusLeaf.hl, {scaleX:this.mapScale * 1.3, scaleY: this.mapScale * 1.3}, 0.3, () => {

        
      });

      //5秒后恢复原状
      setTimeout(() => {
        //荷叶缩小
        tweenChange(lotusLeaf.hl, {scaleX:this.mapScale, scaleY: this.mapScale}, 0.3, ()=>{

          tweenChange(lotusLeaf.hl, {alpha:0}, 0.3, ()=>{    

          });

        });

        tweenChange(lotusLeaf.shadow, {scaleX:this.mapScale, scaleY: this.mapScale}, 0.3);

      }, 2000);

      //阴影放大
      tweenChange(lotusLeaf.shadow, {scaleX:this.mapScale * 1.3, scaleY: this.mapScale * 1.3}, 0.3, () => {
        
      });

      //停留0.1秒，然后跳出
      setTimeout(() => {
        
        let tPos = this.getJumpOutMap2(toX, toY, this.frog.bigLeafX, this.frog.bigLeafY, this.frog.width);

        console.log(toX, toY, 'out pos', tPos);

        this.frogJump(tPos.x, tPos.y, 0.5,()=>{

          //游戏结束
          if(this.tempSmallLotusLeafs.length == 0){
           
            //初始化重新玩游戏状态
            this.initRestartGame();
          }
          else{
            //重置小青蛙，并跳到大荷叶
            this.jumpToBigLotusLeaf();
          }
          

        });
      }, 100);
    });
  }

  /**
   * 如果大荷叶隐藏，则显示；如果显示，则隐藏
   */
  toggleBigLotus() {
    
    if(this.bigLotusLeaf.leafWave.visible){
      this.bigLotusLeaf.leafWave.visible = false;
      this.bigLotusLeaf.shadow.visible = false;
    }
    else{
      this.bigLotusLeaf.leafWave.visible = true;
      this.bigLotusLeaf.shadow.visible = true;
    }
  }


  /**
   * 晃动大荷叶
   */
  shakeWave(){

    let scale = this.mapScale * 1.3;

    //从小变大和透明度变化
    tweenChange(this.bigLotusLeaf.leafWave, {scaleX:scale, scaleY:scale, alpha:0}, 3, ()=>{

      //回到初始大小
      this.bigLotusLeaf.leafWave.setScaleXY(this.mapScale * 0.6);

      //回到初始透明度
      this.bigLotusLeaf.leafWave.alpha = 1;

      this.shakeWave();
      
    });
  }

  /**
   * 青蛙跳跃
   * @param toX 
   * @param toY 
   * @param time
   * @param callback
   */
  frogJump(toX, toY, time:number, callback = null){

    //显示跳越动作
    this.frog.jumpedUp.visible = true;

    //停止动画
    this.frog.animationStop = true;

    let sX = this.frog.bg.x;

    let sY = this.frog.bg.y;

    //计算中间坐标
    let mPos = this.getJumpMiddleMap(toX, toY, sX, sY);

    tweenChange(this.frog.bg, {x : mPos.x, y : mPos.y}, time/2, ()=>{
      tweenChange(this.frog.bg, {x : toX, y : toY}, time, ()=>{

        this.frog.jumpedUp.visible = false;
  
        this.frog.animationStop = false;
  
        if(callback){
          callback();
        }
  
       },null, () =>{
  
        
        
      });
    });
    
  }

  

  /**
   * 获取青蛙跳入水中坐标
   * @param curX 
   * @param curY 
   * @param sX 
   * @param sY 
   * @param width 
   */
  getJumpOutMap2(curX, curY, sX, sY, width){

    //斜率
    let k = (curY - sY)/(curX - sX);

    //取得跳出的坐标
    let outX = 0;

    if(curX <= sX){

      outX = -width;
    }
    else{

      outX = this.canvasWidth + width;
    }

    let outY = k * (outX - curX) + curY;

    return {x : outX, y: outY};
  }

  /**
   * 跳到荷叶上显示小星星
   * @param lotusLeaf 
   */
  showParticle(lotusLeaf){ 

    showPopParticle(this.images.get('star'), {x: lotusLeaf.x,y: lotusLeaf.y - 50} ,this.bg, 15, 40, 120, 2);
  }

  /**
   * 显示结束花瓣
   */
  showPetal(){
    if(!this.playEnd){
      return;
    }

    const petal = this.getPetal();
    this.endRenderArr.push(petal);

    moveItem(petal, petal.x, this.canvasHeight + petal.height * petal.scaleY, petal['time'], () => {
      removeItemFromArr(this.endRenderArr, petal);
    });

    rotateItem(petal, petal['tr'], petal['time']);

    setTimeout(() => {
      this.showPetal();
    }, 100);
  }

  /**
   * 得到花瓣
   */
  getPetal() {

    const petal = new MySprite(this.ctx);

    const id = Math.ceil( Math.random() * 9 );
    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;
  }


  /**
   * 初始化重新开始游戏
   */
  initRestartGame(){

    this.playEnd = true;

    this.playAudio('handclap', false, () => {

      //撒花结束
      this.playEnd = false;

      //等待所有花瓣落下后才能点击
      setTimeout(() => {
        //显示重新开始按钮
        tweenChange(this.btnRestart.sprite, {x: this.btnRestart.showX, y:this.btnRestart.showY}, 0.3);
            
        this.tempSmallLotusLeafs = [... this.smallLotusLeafs];
        
      }, 4000);

      
    });

    //显示花瓣
    this.showPetal();

    //隐藏大荷叶水波
    this.toggleBigLotus();

    //大荷叶划出屏幕
    let toX = this.canvasWidth + this.bigLotusLeaf.lotusLeaf.getBoundingBox().width / 2;
    let toY = this.canvasHeight + this.bigLotusLeaf.lotusLeaf.getBoundingBox().height / 2;
    
    tweenChange(this.bigLotusLeaf.lotusLeaf, {x: toX, y:toY}, 0.5, ()=>{
          
    });
  }

  /**
   * 重新开始游戏
   */
  restartGame(){

    //取练习题
    let exercises = this.data.exercises[0];

    //打乱数组
    let contents = randomSortByArr(exercises.contents);


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

      let audio = this.audioObj[this.smallLotusLeafs[i].audioUrl];

      audio.currentTime = 0;
      audio.pause();

      this.smallLotusLeafs[i].canVoice = false;

      //荷叶
      let leaf = this.smallLotusLeafs[i].leaf;

      //高亮荷叶
      let hlLeaf = this.smallLotusLeafs[i].hl;
      
      if(this.smallLotusLeafs[i].conText){
       
        leaf.removeChild(this.smallLotusLeafs[i].conText);

        hlLeaf.removeChild(this.smallLotusLeafs[i].conText);

        this.smallLotusLeafs[i].conText = null;
      }

      if(this.smallLotusLeafs[i].conPic){
        leaf.removeChild(this.smallLotusLeafs[i].conPic);

        hlLeaf.removeChild(this.smallLotusLeafs[i].conPic);

        this.smallLotusLeafs[i].conPic = null;
      }

      let content = contents[i];

      this.smallLotusLeafs[i].audioUrl = content.audio_url;

      //重新设置显示内容
      this.setContent(content, leaf, hlLeaf, this.smallLotusLeafs[i]);
    }


    this.playGame();
  }

  /**
   * 获取青蛙跳入指定位置的中间坐标
   * @param toX 
   * @param toY 
   * @param sX 
   * @param sY 
   */
  getJumpMiddleMap(toX, toY, sX, sY){

    //斜率
    let k = (toY - sY)/(toX - sX);

    //取得跳出的坐标
    let mX = (sX + toX) / 2;

    let mY = k * (mX - toX) + toY;

    //如果目的地x坐标比原来坐标小，则增加中间高度
    if(sX > toX + 50 * this.mapScale){

      mY = mY - 180 * this.mapScale;
    }

    return {x : mX, y: mY};
  }
}
