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

import {
  Label,
  MySprite, ShapeCircle, ShapeRect, ShapeRoundRect, tweenChange,
  getMinScale
} from './Unit';
import {res, resAudio} from './resources';

import {Subject} from 'rxjs';
import {debounceTime} 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 {

  @ViewChild('canvas') canvas: ElementRef;
  @ViewChild('wrap') 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 = {};

  renderArr;
  mapScale = 1;

  canvasLeft;
  canvasTop;

  saveKey = 'test_008';
 

  canTouch = true;

  curPic;

  //单词画面数组
  word_arr_left = [] ;
  word_arr = [];

  word_bg_x ;

  word_height ;

  all_words_loaded = false;

  curAudio ;
  play = false;
  words_bg ;
  title_bg ;

  wordLoad :{[key:string]:{loaded : boolean;letters:{[key:string]:{loaded:boolean, letter:Label}}}} = {};

  setWordLoad(id: string, letterId:string, loaded:boolean, letter: Label):void{

    if(!this.wordLoad[id]){
      this.wordLoad[id] = {
        loaded:false,
        letters:{}
      }
    }
    let letters = this.wordLoad[id].letters;

    if(!letters[letterId]){
      letters[letterId] = {
        loaded:loaded,
        letter:letter
      }
    }

    //是否存在未加载完成的字母
    let flag = false;

    for(let tKey in letters){
      if(!letters[tKey].loaded){
        flag = true;
        break;
      }
    }

    if(!flag){
      this.wordLoad[id].loaded = true;
    }
    else{
      this.wordLoad[id].loaded = false;
    }


  }

  getWordLoaded(id: string):boolean{

    if(!this.wordLoad[id]){
      return false;
    }
    return this.wordLoad[id].loaded;
  }

  /**
   * 检查单词是否加载完成
   * @param id 单词id
   */
  checkWordLoaded(id: string):void{
    if(!this.wordLoad[id]){
      return;
    }

    let letters = this.wordLoad[id].letters;

    //是否存在未加载完成的字母
    let flag = false;

    for(let tKey in letters){
      if(!letters[tKey].loaded){
        flag = true;
        break;
      }
    }

    if(!flag){
      this.wordLoad[id].loaded = true;
    }
    else{
      this.wordLoad[id].loaded = false;
    }
  }

  getLetterSpriteFromWordLoaded(id: string){

    if(!this.wordLoad[id]){
      return;
    }

    let letters = this.wordLoad[id].letters;

    return letters;
  }

  @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.playAudio("newpage");

    }, this.saveKey);

  }


  /**
   * 初始化标题
   */
  initTitle(){
    const title_bg = new ShapeRect();
    title_bg.x = 70;
    title_bg.y = 0;
    //设置不显示
    title_bg.alpha=0;

    let title_content = this.data.title;
    console.log('title', title_content);

    //标题1
    let title1;

    //标题2
    let title2;

    if(title_content){

      //标题1
      title1 = new Label();    
      title1.text = title_content.t_val1;
      title1.textAlign = 'center';
      title1.fontSize = title_content.t_font_size;
      title1.fontName = title_content.t_font;
      title1.fontColor = title_content.t_font_color;
      title1.refreshSize();
      // title1.setScaleXY(this.mapScale);

      title1.x = (title1.width + 30)/2;
      title1.y = (title1.height + 30)/2;

      //标题2
      title2 = new Label();    
      title2.text = title_content.t_val2;
      title2.textAlign = 'center';
      title2.fontSize = title_content.t_font_size;
      title2.fontName = title_content.t_font;
      title2.fontColor = title_content.t_font_color;
      title2.refreshSize();
      // title2.setScaleXY(this.mapScale);
    }

    //标题1背景
    let title1_bg = new ShapeRect();
    title1_bg.fillColor="#f8c224";

    //将标题1添加到标题背景里
    title_bg.addChild(title1_bg);

     //如果标题1存在，则添加；否则则设置默认值
    if(title1){
      title1_bg.setSize((title1.width + 30) , (title1.height + 30) );
      //将标题1添加到标题1背景里
      title1_bg.addChild(title1);
    }
    else{
      title1_bg.setSize(60 , 50 );
    }
    let title_bg_width = title1_bg.width + 100;
    //如果标题2存在，则添加到标题背景里
    if(title2){
      title_bg.addChild(title2);
      title_bg_width = title1_bg.width + 20 + title2.width
    }

    title_bg.setSize(title_bg_width, title1_bg.height);
    title_bg.setScaleXY(this.mapScale);
    //设置背景1坐标
    title1_bg.x = (title_bg.height - title1_bg.width)/2 ;
    title1_bg.y = 0;
    if(title2){ 
      //设置标题2坐标
      title2.x = title1_bg.width + title2.width/2 + 10; 
      title2.y = title_bg.height/2;
    }
    this.title_bg = title_bg;
    this.renderArr.push(title_bg);
  }


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

  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, callbackParam = null) {

    console.log('add audio', key);
    if(!key){
      return;
    }

    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;

    audio.addEventListener('ended', function () {  
      console.log('play ended');
      if (callback) {
        callback(callbackParam);
      }
    }, false);
  }

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

  defaultWordArr(){
    return [
      {
        left: {
          word_val: 'at',
          word_audio_url: '',
          letters: [
            {letter_val: "a",letter_color: 'C02',is_: '0'},
            {letter_val: "t",letter_color: 'C02',is_: '0'}
          ]
        },
        right: {
          word_val: 'ate',
          word_audio_url: '',
          letters: [
            {letter_val: "a",letter_color: 'C02',is_: '1'},
            {letter_val: "t",letter_color: 'C02',is_: '0'},
            {letter_val: "e",letter_color: 'C02',is_: '1'}
          ]
        }
      },
      {
        left: {
          word_val: 'rat',
          word_audio_url: '',
          letters: [
            {letter_val: "r",letter_color: 'C04',is_: '0'},
            {letter_val: "a",letter_color: 'C02',is_: '0'},
            {letter_val: "t",letter_color: 'C02',is_: '0'}
          ]
        },
        right: {
          word_val: 'ate',
          word_audio_url: '',
          letters: [
            {letter_val: "r",letter_color: 'C04',is_: '0'},
            {letter_val: "a",letter_color: 'C02',is_: '1'},
            {letter_val: "t",letter_color: 'C02',is_: '0'},
            {letter_val: "e",letter_color: 'C02',is_: '1'}
          ]
        }
      },
      {
        left: {
          word_val: 'cap',
          word_audio_url: '',
          letters: [
            {letter_val: "c",letter_color: 'C04',is_: '0'},
            {letter_val: "a",letter_color: 'C02',is_: '0'},
            {letter_val: "p",letter_color: 'C02',is_: '0'}
          ]
        },
        right: {
          word_val: 'capexxxxxxxx',
          word_audio_url: '',
          letters: [
            {letter_val: "c",letter_color: 'C04',is_: '0'},
            {letter_val: "a",letter_color: 'C02',is_: '1'},
            {letter_val: "p",letter_color: 'C02',is_: '0'},
            {letter_val: "e",letter_color: 'C02',is_: '1'},
            {letter_val: "x",letter_color: 'C02',is_: '1'},
            {letter_val: "x",letter_color: 'C02',is_: '1'},
            {letter_val: "x",letter_color: 'C02',is_: '1'},
            {letter_val: "x",letter_color: 'C02',is_: '1'},
            {letter_val: "x",letter_color: 'C02',is_: '1'},
            {letter_val: "x",letter_color: 'C02',is_: '1'},
            {letter_val: "x",letter_color: 'C02',is_: '1'},
            {letter_val: "x",letter_color: 'C02',is_: '1'}
          ]
        }
      },
      {
        left: {
          word_val: 'tap',
          word_audio_url: '',
          letters: [
            {letter_val: "t",letter_color: 'C04',is_: '0'},
            {letter_val: "a",letter_color: 'C02',is_: '0'},
            {letter_val: "p",letter_color: 'C02',is_: '0'}
          ]
        },
        right: {
          word_val: 'tape',
          word_audio_url: '',
          letters: [
            {letter_val: "t",letter_color: 'C04',is_: '0'},
            {letter_val: "a",letter_color: 'C02',is_: '1'},
            {letter_val: "p",letter_color: 'C02',is_: '0'},
            {letter_val: "e",letter_color: 'C02',is_: '1'}
          ]
        }
      },
      {
        left: {
          word_val: 'can',
          word_audio_url: '',
          letters: [
            {letter_val: "c",letter_color: 'C04',is_: '0'},
            {letter_val: "a",letter_color: 'C02',is_: '0'},
            {letter_val: "n",letter_color: 'C02',is_: '0'}
          ]
        },
        right: {
          word_val: 'cane',
          word_audio_url: '',
          letters: [
            {letter_val: "c",letter_color: 'C04',is_: '0'},
            {letter_val: "a",letter_color: 'C02',is_: '1'},
            {letter_val: "n",letter_color: 'C02',is_: '0'},
            {letter_val: "e",letter_color: 'C02',is_: '1'}
          ]
        }
      },
      {
        left: {
          word_val: 'mat',
          word_audio_url: '',
          letters: [
            {letter_val: "m",letter_color: 'C04',is_: '0'},
            {letter_val: "a",letter_color: 'C02',is_: '0'},
            {letter_val: "t",letter_color: 'C02',is_: '0'}
          ]
        },
        right: {
          word_val: 'mate',
          word_audio_url: '',
          letters: [
            {letter_val: "m",letter_color: 'C04',is_: '0'},
            {letter_val: "a",letter_color: 'C02',is_: '1'},
            {letter_val: "t",letter_color: 'C02',is_: '0'},
            {letter_val: "e",letter_color: 'C02',is_: '1'}
          ]
        }
      },
      {
        left: {
          word_val: 'man',
          word_audio_url: '',
          letters: [
            {letter_val: "m",letter_color: 'C04',is_: '0'},
            {letter_val: "a",letter_color: 'C02',is_: '0'},
            {letter_val: "n",letter_color: 'C02',is_: '0'}
          ]
        },
        right: {
          word_val: 'mane',
          word_audio_url: '',
          letters: [
            {letter_val: "m",letter_color: 'C04',is_: '0'},
            {letter_val: "a",letter_color: 'C02',is_: '1'},
            {letter_val: "n",letter_color: 'C02',is_: '0'},
            {letter_val: "e",letter_color: 'C02',is_: '1'}
          ]
        }
      },
      {
        left: {
          word_val: 'van',
          word_audio_url: '',
          letters: [
            {letter_val: "v",letter_color: 'C04',is_: '0'},
            {letter_val: "a",letter_color: 'C02',is_: '0'},
            {letter_val: "n",letter_color: 'C02',is_: '0'}
          ]
        },
        right: {
          word_val: 'vane',
          word_audio_url: '',
          letters: [
            {letter_val: "v",letter_color: 'C04',is_: '0'},
            {letter_val: "a",letter_color: 'C02',is_: '1'},
            {letter_val: "n",letter_color: 'C02',is_: '0'},
            {letter_val: "e",letter_color: 'C02',is_: '1'}
          ]
        }
      }
    ];
  }

  /**
   * 添加默认数据 便于无数据时的展示
   */
  initDefaultData() {

    if(!this.data.title){
      this.data.title = this.getDefaultTitle();
    }

    if(!this.data.words){
      this.data.words = "a_e";
    }
    if (!this.data.wordArr) {
      this.data.wordArr = this.defaultWordArr();
    }

    this.title_bg = {};

    this.listenPlaying = false;

    this.listenPlayStatus = {};


  }

  getDefaultTitle(){
    return {
      t_val1:'C',
      t_val2:'Listen, write circle and read.',
      t_font_color:'#000000',
      t_font:'BRLNSDB',
      t_font_size:40
    };
  }


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

    this.addUrlToImages(this.data.pic_url);
    this.addUrlToImages(this.data.pic_url_2);

  }

  /**
   * 添加预加载音频
   */
  initAudio() {
    // 音效
    this.addUrlToAudioObj('click', this.rawAudios.get('click'), 0.3);

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

    // 听力资料
    this.addUrlToAudioObj(this.data.listen_audio_url, null,1, false, function(listenPlayStatus){
      listenPlayStatus.play.alpha=1;
      listenPlayStatus.pasue.alpha = 0;
    },this.listenPlayStatus);

    // 音频资源
    this.addUrlToAudioObj(this.data.title.t_audio_url);

    this.addUrlToAudioObj(this.data.words_audio_url);

    // 初始化单词音效
    for (let i = 0; i < this.data.wordArr.length; ++ i) {
       let wordLeft = this.data.wordArr[i].left;
       if (wordLeft.word_audio_url && wordLeft.word_audio_url != '') {
          this.addUrlToAudioObj(wordLeft.word_audio_url);
       }

       let wordRight = this.data.wordArr[i].right;
       if (wordRight.word_audio_url && wordRight.word_audio_url != '') {
          this.addUrlToAudioObj(wordRight.word_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.renderArr = [];
    this.word_arr_left = [] ;
    this.word_arr = [];
    this.word_bg_x = 200 ;

    this.word_height = 0 ;

    this.all_words_loaded = false;

    this.wordLoad = {};

    this.play = false ;

  }



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


    this.initPic();

    this.initBottomPart();

  }

  initBottomPart() {

    const btnPlay = new MySprite();
    btnPlay.init(this.images.get('play'));
    btnPlay.x = this.canvasWidth - 50 * this.mapScale;
    btnPlay.y = this.canvasHeight - 50 * this.mapScale;

    btnPlay.setScaleXY(this.mapScale);
    btnPlay.alpha = 1;

    this.renderArr.push(btnPlay);

    this.listenPlayBtn = btnPlay;

    this.listenPlayStatus.play = btnPlay;



    const btnPause = new MySprite();
    btnPause.init(this.images.get('pause'));
    btnPause.x = btnPlay.x;
    btnPause.y = btnPlay.y;
    btnPause.alpha = 0;
    btnPause.setScaleXY(this.mapScale);

    this.renderArr.push(btnPause);

    this.listenPauseBtn = btnPause;

    this.listenPlayStatus.pasue = btnPause;
  }

  body_bg;

  initPic() {

    this.body_bg = new ShapeRoundRect();
   // 初始化单词显示
    this.initWord();
 
    // let wordNum = this.data.wordArr.length; 
    // for (let i = 0; i < wordNum; ++ i) { 
    //   this.body_bg.addChild(this.word_bg_groups[i]) ;  
    // }
    this.body_bg.setSize(1000*this.mapScale, 520*this.mapScale, 30*this.mapScale) ;
    this.body_bg.x = (this.canvasWidth - this.body_bg.width) / 2 ;
    this.body_bg.y = this.canvasHeight - this.body_bg.height - (this.canvasHeight - this.body_bg.height)/3 ;
    this.body_bg.setOutLine('#faebad',4) ;
    // this.body_bg.setScaleXY(this.mapScale);  

    this.renderArr.push(this.body_bg);

    const words_bg = new ShapeCircle();
    words_bg.setRadius(50);
    words_bg.fillColor = '#fdcd00' ;
    words_bg.x = this.body_bg.width / 2  ;
    words_bg.y = 0;

    const words_content = new Label();
    words_content.text = this.data.words;
    words_content.textAlign = 'center';
    words_content.fontSize = 50;
    words_content.fontName = 'GOTHICB';
    words_content.fontWeight = 600;
    words_content.fontColor = '#ab5a23';
    words_content.refreshSize(); 
    words_bg.addChild(words_content);
    words_bg.setScaleXY(this.mapScale); 

    this.body_bg.addChild(words_bg); 
    this.words_bg = words_bg ; 
 
  }

  /**
   * 初始化单词显示
   */
  initWord() {
     this.drawWordSprite();
  }

  cricleNumber(num){
    const bg = new ShapeCircle();
    bg.setRadius(20);
    bg.fillColor = '#f9ebb0' ; 

    const words_content = new Label();
    words_content.text = num;
    words_content.textAlign = 'center';
    words_content.fontSize = 25;
    words_content.fontName = 'GOTHICB';
    words_content.fontWeight = 600;
    words_content.fontColor = '#fff';
    words_content.refreshSize(); 
    bg.addChild(words_content);
    bg.setScaleXY(this.mapScale); 
    return bg;
  }

  
  /**
   * 绘画单词
   */
  word_bg_groups = [];
  drawWordSprite() {

    const getWordSprite = (index , x , y) => {

      let letterFontSize = 40;
      // 单词背景 
      let word_bg_group = new ShapeRect();
      word_bg_group.fillColor = '#ffffff' ;
      word_bg_group.x = (x + 60) * this.mapScale;
      word_bg_group.y = (y + 80) * this.mapScale;

      let start = this.cricleNumber(index+1); 
      start.y = start.height / 2 ;
      start.x = start.width / 2;
      word_bg_group.addChild(start) ;
      let startWidth = 40;

      //单词
      let word_bg = new ShapeRect();
      word_bg.fillColor = 'transparent' ;
      word_bg.x = startWidth ;  //序号间距
      word_bg.y = 0;
      let word_content = this.data.wordArr[index];
      let totalWidth = 0;
      let height = 0;
      let letter_spr_arr = [];
      for(let i = 0; i < word_content.left.letters.length; ++ i) {
        //字母
        let letter = word_content.left.letters[i];
        // console.log('letter:',letter) ;
        let letter_spr = new Label(); 
        letter_spr.text = letter.letter_val;
        if(letter.is_=="0"){
          //设置不显示
          letter_spr.visible = true; 
        }else{
          word_bg["wordLoaded"] = false; 
          //设置不显示
          letter_spr.visible = false; 
        } 

        letter_spr.textAlign = 'left';
        // letter_spr.fontSize = word_content.word_font_size ? word_content.word_font_size : 110;
        letter_spr.fontSize =  letterFontSize;
        letter_spr.fontName = 'MMTextBook';
        letter_spr.fontColor = this.getColor(letter.letter_color);
        //设置不显示
        letter_spr.visible = true;
        letter_spr.refreshSize();
        letter_spr_arr.push(letter_spr);
        //设置坐标
        letter_spr.x = letter_spr.width/2+totalWidth+5;
        letter_spr.y = letter_spr.height/2;

        if(letter.is_=="1"){
          let lts_ = new Label();
          lts_.text = "_";
          lts_.textAlign = 'left'; 
          lts_.fontSize =  letterFontSize;
          lts_.fontName = 'MMTextBook';
          lts_.fontColor = this.getColor(letter.letter_color);
          lts_.x = letter_spr.x; 
          lts_.y = letter_spr.y+2;
          lts_.visible = true; 
          word_bg.addChild(lts_);
        }

        height = letter_spr.height;
        if(index === 0){
           this.word_height = height ;
        }

        totalWidth += letter_spr.width+10;
        word_bg.addChild(letter_spr);
      } 

      word_bg.setSize(totalWidth, height);
      // let minScale = getMinScale(word_bg, 120);
      // word_bg.setScaleXY(minScale); 
      word_bg_group.addChild(word_bg);

      this.word_arr_left.push(word_bg); 

      //中间斜杠
      let splitStr = new Label();
      let splitStrWidth = 60;
      splitStr.text = '/';
      splitStr.textAlign = 'center'; 
      splitStr.fontSize =  letterFontSize;
      splitStr.fontName = 'MMTextBook';
      splitStr.fontColor = 'black';
      //设置不显示
      splitStr.visible = true;  
      splitStr.refreshSize();
      splitStr.y = splitStr.height / 2 ;
      splitStr.x = startWidth + totalWidth + 40 ;
      word_bg_group.addChild(splitStr) ;
       
      //=============================右侧单词========================================
      // 单词背景
      let word_bg_right = new ShapeRect();
      word_bg_right.fillColor = 'transparent' ;
      word_bg_right.x =  startWidth + totalWidth + splitStrWidth;
      word_bg_right.y = 0;
      word_bg_right["wordLoaded"] = true;

      //单词
      let totalWidth_right = 0;
      let height_right = 0;
      let letter_spr_arr_right = [];
      for(let i = 0; i < word_content.right.letters.length; ++ i) { 
        //字母
        let letter = word_content.right.letters[i]; 
        let letter_spr = new Label();
        letter_spr.text = letter.letter_val;
        if(letter.is_=="0"){
          //设置不显示
          letter_spr.visible = true; 
        }else{
          word_bg_right["wordLoaded"] = false; 
          //设置不显示
          letter_spr.visible = false; 
        } 
        letter_spr.textAlign = 'left'; 
        letter_spr.fontSize =  letterFontSize;
        letter_spr.fontName = 'MMTextBook';
        letter_spr.fontColor = this.getColor(letter.letter_color);
        
        letter_spr.refreshSize(); 
        letter_spr_arr_right.push(letter_spr);

        //设置坐标
        letter_spr.x = Math.ceil(letter_spr.width/2) + totalWidth_right +5; 
        letter_spr.y = letter_spr.height/2;

        if(letter.is_=="1"){
          let lts_ = new Label();
          lts_.text = "_";
          lts_.textAlign = 'left'; 
          lts_.fontSize =  letterFontSize;
          lts_.fontName = 'MMTextBook';
          lts_.fontColor = this.getColor(letter.letter_color);
          lts_.x = letter_spr.x; 
          lts_.y = letter_spr.y+2;
          lts_.visible = true; 
          word_bg_right.addChild(lts_);
        }

        height_right = letter_spr.height;
        totalWidth_right += letter_spr.width+10; 
        // 设置单词未加截完
        // this.setWordLoad(index, String(i), false, letter_spr);

        word_bg_right.addChild(letter_spr);
      } 

      word_bg_right.setSize(totalWidth_right, height_right);
      word_bg_group.addChild(word_bg_right) ;
      word_bg_group.setSize((totalWidth_right+totalWidth+splitStrWidth+startWidth), height);  
      if(word_bg_group.width>350){
        word_bg_group.setScaleXY(getMinScale(word_bg_group, 350)*this.mapScale); 
      }else{
        word_bg_group.setScaleXY(this.mapScale); 
      } 
      
      this.word_arr.push(word_bg_right); 
      this.word_bg_groups.push(word_bg_group);
      this.body_bg.addChild(word_bg_group);
    };

    //单词个数
    let wordNum = this.data.wordArr.length; 
    // console.log('line: ', line) ;
    for (let i = 0; i < wordNum; i++) {
      let x = 0;
      let y = this.word_height*i*2.7;
      if(i>3){
        x = 500;
        y = this.word_height*(i-4)*2.7;
      }

      getWordSprite(i , x , y);  
    }
  }

  /**
   * 根据颜色id获取对应的颜色
   * @param colorId 颜色id
   */
  getColor(colorId){

    let color = "#000000";

    switch(colorId){
      case "C01":
        color = "#008000";
        break;
      case "C02":
        color = "#FF0000";
        break;
      case "C03":
        color = "#D2691E";
        break;
      case "C04":
        color = "#000000";
        break;
    }

    return color;
  }

  pauseClicked() {
     if(this.curAudio){
         if(this.play){
            this.curAudio.pause() ;
            this.play = false ;
         }else {
           this.curAudio.play() ;
           this.play = true ;
         }
     }
  }
  

  //听力材播放按钮
  listenPlayBtn;

  //听力材暂停按钮
  listenPauseBtn;

  listenPlaying = false;

  listenPlayStatus;


  mapDown(event) {

    if (!this.canTouch) {
      return;
    }

    if (this.checkClickTarget(this.title_bg)) {
      // console.log('click the words :' , this.data.words_audio_url) ;
      this.playAudio(this.data.title.t_audio_url) ;
      return ;
    }

    if (this.checkClickTarget(this.words_bg)) {
        // console.log('click the words :' , this.data.words_audio_url) ;
        this.playAudio(this.data.words_audio_url) ;
        return ;
    }

    for(let i = 0; i < this.word_arr_left.length; ++ i){
      let word = this.word_arr_left[i];
      // console.log('word', word) ;
      if (this.checkClickTarget(word)) {
        console.log('this word left: ', this.data.wordArr[i]) ;
        this.playAudio(this.data.wordArr[i].left.word_audio_url);
        return ;
      }

    }

    for(let i = 0; i < this.word_arr.length; ++ i){
      let word = this.word_arr[i];
      // console.log('word', word) ;
      if (this.checkClickTarget(word)) { 
        // 获取是否加载完成
        let loaded = word.wordLoaded;
        // 未加载，不触发音效，加载单词
        if (!loaded) {
          let letters:Array<Label> = word.children.slice(1); 
          for (let j=0; j<letters.length;j++) {
            let labelItem = letters[j];
            if(!labelItem.visible){
              labelItem.visible = true;
            } 
          }
          word.wordLoaded = true;
          return ;
        } 
        this.playAudio(this.data.wordArr[i].right.word_audio_url);
        return ;
      }

    }
  
    if (this.checkClickTarget(this.listenPlayBtn) && !this.listenPlaying) {
      
      this.listenPlayBtn.alpha = 0;

      this.listenPauseBtn.alpha = 1;

      this.playAudio(this.data.listen_audio_url);

      this.listenPlaying = true;

      return;
    }

    if (this.checkClickTarget(this.listenPauseBtn) && this.listenPlaying) {
      
      this.listenPlayBtn.alpha = 1;

      this.listenPauseBtn.alpha = 0;

      this.pauseAudio(this.data.listen_audio_url);

      this.listenPlaying = false;

      return;
    } 

  }

  mapMove(event) {

  }

  mapUp(event) {

  }



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


  }



}
