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

import {
  MySprite,
  Label,
  moveItem,
  rotateItem,
  removeItemFromArr,
  ShapeRect, scaleItem, tweenChange, showPopParticle, hideItem, showItem, LineRect, shake, RichText, ShapeRectNew, showShapeParticle, delayCall, randomSortByArr, ScrollView, InputView, ShapeCircle, MyVideo, getMinScale,

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

import { loadFonts } from './Util'
import { faTshirt } from '@fortawesome/free-solid-svg-icons';
import { DomSanitizer } from '@angular/platform-browser';
import { checkAnswer } from './checker';
import { HttpClient } from '@angular/common/http';




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

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

  @Input()
  sid;

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

  @ViewChild('videoNode', {static: true }) videoNode: ElementRef;
  @ViewChild('tpl', {static: true }) tpl: TemplateRef<void>;
  @ViewChild('videoContainer', {static: true }) videoContainer: ElementRef;

  

  canvasScale = 2;

  canvasWidth = 2388;
  canvasHeight = 1688;

  canvasBaseW = 2388;
  canvasBaseH = 1688;


  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;
  mapScaleMax = 1;

  canvasLeft;
  canvasTop;


  canTouch = true;


  KEY = 'JM_MATH01';

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


  pageLabel;
  leftBtn;
  rightBtn;
  bgLayer;
  curPageIndex;

  hotZoneArr;

  picIndex = 0;


  bgArr;
  endPageArr;
  gameEndFlag;
  showPetalFlag;
  bg;
  topArr;



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

  }


  constructor(private http: HttpClient, private sanitizer: DomSanitizer, private appRef: ApplicationRef, private container: ViewContainerRef) {

  }

  isTeacher = false;

  async ngOnInit() {



    await loadFonts('DroidSansFallback', 'DroidSansFallback.ttf');
    await loadFonts('Aileron-Black', 'Aileron-Black.ttf');
    await loadFonts('Aileron-Bold', 'Aileron-Bold.ttf');

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


      if (window['air']?.airClassInfo?.user?.classRole == 'tea') {
        this.isTeacher = true;
      }
			if (aspect) {
        console.log('aspect : ', aspect);
				this.initPageData(aspect);
				this.initStoreData(aspect);
      }

      if (data && typeof data == 'object') {
        this.data = { contentObj: data };
      } else {

        this.initDefaultData();
      }

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




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


    }, this.KEY);


  }



  	// 用于存储私有数据 当翻页时清空 
	storeData;
	initStoreData(aspect) {
		const storeDataStr = aspect?.user_aspect;
		if (!storeDataStr) {
			this.storeData = {};
		} else {
			this.storeData = JSON.parse(storeDataStr);
		}
		console.log('this.storeData: ', this.storeData);
	}

  setStoreData(key, value, isSend=true) {

		if (this.storeData) {

			console.log('this.storeData: ', this.storeData);
			this.storeData[key] = value;
			if (isSend) {
				this.sendStoreData();
			}
		}

  }

  getStoreData(key) {
		return this.storeData && this.storeData[key];
  }

  sendStoreData() {

		const data = this.storeData;

		if (window && window['courseware']) {
			let storeAspect = window['courseware'].storeAspect;
			if (storeAspect) {
				storeAspect(data);
			}
		}
	}



	// 用于存储公共数据 当翻页时清空 
	pageData;
	initPageData(aspect) {
		const pageDataStr = aspect?.page_aspect?.pagedata;
		if (!pageDataStr) {
			this.pageData = {};
		} else {
			this.pageData = JSON.parse(pageDataStr);
		}
		console.log('this.pageData: ', this.pageData);
	}

	setPageData(key, value, isSend=true) {

		if (this.pageData) {

			console.log('this.pageData: ', this.pageData);
			this.pageData[key] = value;
			if (isSend) {
				this.sendPageData();
			}
		}
	}

	getPageData(key) {
		if (this.pageData && this.pageData[key] != null) {
			return this.pageData[key];
		}
	}

	sendPageData() {

		const data = this.pageData;

		if (window && window['courseware']) {
			let storePageAspect = window['courseware'].storePageAspect;
			if (storePageAspect) {
				storePageAspect(data);
			}
		}
	}



  initDefaultData() {

    const data = {"sentenceArr":[],"templateArr":[],"bg_url":"http://staging-teach.cdn.ireadabc.com/1aaccbaa8f3a32df099f3308feac49e7.png","title":"new word","bgItem":{"url":"http://staging-teach.cdn.ireadabc.com/e3672206ffa9736c449b64d05f688b30.png","rect":{"x":102.83,"y":0,"width":485.33,"height":273}},"hotZoneItemArr":[{"id":"1634265930328","index":0,"itemType":"rect","fontScale":0.53984375,"imgScale":1,"imgSizeW":0,"imgSizeH":0,"mapScale":0.53984375,"dragDot":{"x":345.5,"y":133.26904532304724},"gIdx":"0","selectType":"JJ","posX":282.5,"posY":52,"rect":{"x":13.35,"y":22.52,"width":136.5,"height":25.94}},{"id":"1634265945079","index":1,"itemType":"rect","fontScale":0.53984375,"imgScale":1,"imgSizeW":0,"imgSizeH":0,"mapScale":0.53984375,"dragDot":{"x":345.5,"y":133.26904532304724},"gIdx":"0","selectType":"RB","posX":552.5,"posY":59,"rect":{"x":197.63,"y":27.98,"width":136.5,"height":24.57}},{"id":"1634265955820","index":2,"itemType":"rect","fontScale":0.53984375,"imgScale":1,"imgSizeW":0,"imgSizeH":0,"mapScale":0.53984375,"dragDot":{"x":345.5,"y":133.26904532304724},"gIdx":"0","selectType":"WP","posX":281.5,"posY":129,"rect":{"x":12.67,"y":73.71,"width":136.5,"height":28.67}},{"id":"1634265962408","index":3,"itemType":"rect","fontScale":0.53984375,"imgScale":1,"imgSizeW":0,"imgSizeH":0,"mapScale":0.53984375,"dragDot":{"x":345.5,"y":133.26904532304724},"gIdx":"0","selectType":"CD","posX":548.5,"posY":132,"rect":{"x":194.9,"y":75.08,"width":136.5,"height":30.03}},{"id":"1634265967558","index":4,"itemType":"rect","fontScale":0.53984375,"imgScale":1,"imgSizeW":0,"imgSizeH":0,"mapScale":0.53984375,"dragDot":{"x":345.5,"y":133.26904532304724},"gIdx":"0","selectType":"IN","posX":284.5,"posY":213,"rect":{"x":14.72,"y":131.72,"width":136.5,"height":27.3}},{"id":"1634266027751","index":5,"itemType":"rect","fontScale":0.53984375,"imgScale":1,"imgSizeW":0,"imgSizeH":0,"mapScale":0.53984375,"dragDot":{"x":345.5,"y":133.26904532304724},"gIdx":"0","selectType":"VB","posX":292.5,"posY":320,"rect":{"x":20.18,"y":202.7,"width":136.5,"height":31.4}},{"id":"1634266044165","index":6,"itemType":"rect","fontScale":0.53984375,"imgScale":1,"imgSizeW":0,"imgSizeH":0,"mapScale":0.53984375,"dragDot":{"x":345.5,"y":133.26904532304724},"gIdx":"0","selectType":"NN","posX":544.5,"posY":308,"rect":{"x":192.17,"y":194.51,"width":136.5,"height":31.4}},{"id":"1634266050496","index":7,"itemType":"rect","fontScale":0.53984375,"imgScale":1,"imgSizeW":0,"imgSizeH":0,"mapScale":0.53984375,"dragDot":{"x":345.5,"y":133.26904532304724},"gIdx":"0","selectType":"NN","posX":759.5,"posY":323,"rect":{"x":338.91,"y":204.75,"width":136.5,"height":31.4}}]}

    this.data = { contentObj: data };
    

  }

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

  sentenceArr = [];
  submitCount = 0;
  safeDefaultUrl;
  resultAnswerArr;

  scrollView;
  resultSv;
  userResultPic;
  userResultData;
  uploadUrl;



  templateQuesType;
  TYPE_SHORT_ANSWER = 'short_answer';
  TYPE_SINGLE_CHOICE = 'single_choice';
  initData() {
    

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

    this.canvas.nativeElement.width = this.wrap.nativeElement.clientWidth * this.canvasScale;
    this.canvas.nativeElement.height = this.wrap.nativeElement.clientHeight * this.canvasScale;


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

    this.mapScaleMax = Math.max(sx, sy);

   
    this.renderArr = [];
    this.topArr = [];
    this.userResultPic = null;
    this.userResultData = null;

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


    this.templateQuesType = this.data.contentObj.ques_type;

    

    this.uploadUrl = (<any> window).courseware.uploadUrl();
    window['air'].getUploadCallback = (url, data) => {
      this.uploadUrl = url;
    };



    this.canTouch = true;

    this.submitCount = 0;
    this.replaceSentenceText();

    this.safeDefaultUrl = this.sanitizer.bypassSecurityTrustResourceUrl(''); 

    this.resultAnswerArr = [];

    this.resultSv = null;

  }

  replaceSentenceText() {
    const arr = this.data.contentObj.sentenceArr;
    if (!arr) {
      console.error('没有数据')
      return;
    }

    this.sentenceArr = JSON.parse(JSON.stringify(arr));
    for (let i=0; i<this.sentenceArr.length; i++) {
      const text = this.sentenceArr[i].text;
      this.sentenceArr[i].text = text.replace(/_/, "____________________")
    }
  }



  initAudio() {

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



    // const addAudio = (key) => {
    //   const audioUrl = contentObj[key];
    //   if (audioUrl) {
    //     const audio = new Audio();
    //     audio.src = audioUrl;
    //     audio.load();
    //     this.audioObj[key] = audio;
    //   }
    // }
    //
    // for (let i = 0; i < 4; i ++) {
    //   const key = i + '_audio_url';
    //   addAudio(key);
    // }
    //
    // addAudio('audio_url');
    //


    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.hotZoneItemArr;
    addUrlToAudioObj(contentObj.title_audio_url);
    addUrlToAudioObj(contentObj.answer_obj.title_audio_url);
    addUrlToAudioObj(contentObj.choice_obj.title_audio_url);


    if (arr) {
      // console.log('arr: ', arr);
      for (let i = 0; i < arr.length; i++) {
        addUrlToAudioObj(arr[i].audio_url);
      }
    }

    const optionArr = contentObj.optionArr;
    for (let i=0; i<optionArr.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'), 1);
    addOneAudio('more', this.rawAudios.get('more'), 0.8);
    addOneAudio('submit', this.rawAudios.get('submit'), 0.8);
  
    // addOneAudio('cow_start', this.rawAudios.get('cow_start'), 1);
    // addOneAudio('eat', this.rawAudios.get('eat'), 1);
    // addOneAudio('grass', this.rawAudios.get('grass'), 1);
    // addOneAudio('happy', this.rawAudios.get('happy'), 1);
    // addOneAudio('right', this.rawAudios.get('right'), 1);
    // addOneAudio('wrong', this.rawAudios.get('wrong'), 1);



    //
    // const titleUrl = this.data.contentObj.title_audio_url;
    // if (titleUrl) {
    //
    //   this.titleAudio.src = titleUrl;
    //   this.titleAudio.load();
    // }



    // this.bgAudio.src = 'assets/bat-mail/music/bg.mp3';
    // this.bgAudio.load();
    // this.bgAudio.loop = true;
    // this.bgAudio.volume = 0.5;
    //
    // this.wrongAudio.src = 'assets/common/music/wrong.mp3';
    // this.wrongAudio.load();
    //
    // this.rightAudio.src = 'assets/common/music/right.mp3';
    // this.rightAudio.load();
    //
    // this.successAudio.src = 'assets/magic-hat/music/finish.mp3';
    // this.successAudio.load();
    //
    // this.successAudio.onended = () => {
    //   // this.showSuccessAudio();
    // };


  }

  videoObj;
  preloadVideo() {

    this.videoObj = {};
    const addVideoUrl = (video_url) => {

      if (!video_url) {
        return;
      }

      const videoElement = document.createElement('video');
      videoElement.src = video_url;
      this.videoContainer.nativeElement.appendChild(videoElement);

      console.log('tmpV: ', videoElement);

      const video = new MyVideo();
      video.initVideoElement(videoElement);
      video.setScaleXY(this.mapScale);
      video.element.src = video_url;
      video.element.load();
      this.videoObj[video_url] = video;

      video.element.addEventListener('canplaythrough', () => {
        this.refreshVideoSize(video);
      });
    }

    
    const optionArr = this.data.contentObj.optionArr;
    for (let i=0; i<optionArr.length; i++) {
      addVideoUrl(optionArr[i].video_url || '');
      
      const op2Arr = optionArr[i];
      for (let j=0; j<op2Arr.length; j++) {
        addVideoUrl(op2Arr[j].pic_url || '');
      }
    }
  }

  initImg() {

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


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

      let arr = contentObj.hotZoneItemArr;
      if (arr) {

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

          console.log('arr[i].pic_url: ', arr[i].pic_url);
          addPicUrl(arr[i].pic_url);
        }
      }

      addPicUrl(contentObj.bgItem?.url || '');
      addPicUrl(contentObj.bg_url || '');
      addPicUrl(contentObj.ques_pic_url || '');
      addPicUrl(contentObj.title_pic_url || '');
      addPicUrl(contentObj.answer_obj.ques_pic_url || '');
      addPicUrl(contentObj.answer_obj.title_pic_url || '');
      addPicUrl(contentObj.choice_obj.ques_pic_url || '');
      addPicUrl(contentObj.choice_obj.title_pic_url || '');

    
      const choiceOptionArr = contentObj.choice_obj.optionArr;
      for (let i=0; i<choiceOptionArr.length; i++) {
        addPicUrl(choiceOptionArr[i].pic_url || '');
        addPicUrl(choiceOptionArr[i].title_pic_url || '');
        addPicUrl(choiceOptionArr[i].ques_pic_url);
        
      }

      const optionArr = contentObj.optionArr;
      for (let i=0; i<optionArr.length; i++) {
        addPicUrl(optionArr[i].pic_url || '');
        addPicUrl(optionArr[i].title_pic_url || '');
        addPicUrl(optionArr[i].ques_pic_url);

        
        const optionArr2 = optionArr[i].optionArr;
        for (let j=0; j<optionArr2.length; j++) {
          addPicUrl(optionArr2[j].pic_url || '');
        }

        
      }

    }


   

    // this.initFontImg();


    

    // 预加载资源
 


    this.loadResources().then(() => {
      // this.setfontData();


      this.addServerListener();
      window['air'].hideAirClassLoading(this.KEY, this.data);


    });

  }

  loadEnd(cb) {
    this.init();
    this.update();

    cb()
  }

  addServerListener() {
    console.log(' in addServerListener');

    const air = window['air']
		if (air) {
      air.onCourseInScreen = (next) => {
        //各种逻辑
        // this.showTemplateStartAnima();
        console.log('in onCourseInScreen')
        this.loadEnd(() => {
          next();
        });
      }
		}

    const c = window['courseware'];
		if (!c) {
			console.log(' window.courseware not exist !!!!!!!!')

			return;
		}



		c.onEvent('game_start', (data, next) => {
      
      
			this.loadEnd(_=>{});
      if (next) {
        next();
      }
		});
  }


	sendServerEvent(key, data) {

    const c = window['courseware'];
		if (c) {
			c.sendEvent(key, data);
		}
  }

  localStartTime = new Date().getTime();
  gameStart() {
    // this.localStartTime = new Date().getTime();
    // console.log(' in gameStart ');
    // if (this.isTeacher) {
    //   this.sendBtn.visible = false;
    //   this.sendBtn.shadowSpr.visible = false;
    //   this.maskPic.visible = true;
    // } else {
    //   // this.changeBtnOn();
    //   this.maskPic.visible = false;

    // }
  }







  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.setOneBtn();
    // this.initMaskPic();
    // this.relink();
  
    // this.checkShowSubmit();


    this.initVideo();



    if (this.data.contentObj.ques_type == this.TYPE_SINGLE_CHOICE) {
      this.playHotZoneItemSC();
    } else {
      this.playHotZoneItemSA();
    }


  }

  videoCloseBtn;
  videoBg;
  videoMask;
  replayBtn;
  initVideo() {

    const videoMask = new ShapeRect();
    videoMask.setSize(this.canvasWidth, this.canvasHeight);
    videoMask.fillColor = '#f4ecd8';
    videoMask.alpha = 0.7;
    this.topArr.push(videoMask);
    this.videoMask = videoMask;
    videoMask.visible = false;

    const videoBg = this.getMySprite('video_bg');
    videoBg.setScaleXY(this.mapScale);
    videoBg.visible = false;

    // videoBg.anchorX = 1;
    videoBg.x = this.canvasWidth / 2 - videoBg.width / 2 * videoBg.scaleX;
    videoBg.y = this.canvasHeight / 2;
    this.topArr.push(videoBg); 
    this.videoBg = videoBg;

    const videoCloseBtn = this.getMySprite('btn_close');
    videoCloseBtn.x = videoBg.width / 2 - 100;
    videoCloseBtn.y = -videoBg.height / 2 + 53;
    videoBg.addChild(videoCloseBtn);

    this.videoCloseBtn = videoCloseBtn;

    const replayBtn = this.getMySprite('btn_replay')
    this.videoBg.addChild(replayBtn);
    replayBtn.y = this.videoBg.height / 2 - 130;
    replayBtn.visible = false;
    this.replayBtn = replayBtn;


  }

  curVideo;
  initVideoPlayer(data) {
    
    if (this.curVideo) {
      this.curVideo.parent.removeChild(this.curVideo);
      this.curVideo = null;
    }
    const video = this.videoObj[data.video_url];
    if (video) {

      this.videoBg.addChild(video);
      this.refreshVideoSize(video);
      video.element.currentTime = 0.01;
      video.element.play();
      this.curVideo = video;

      this.replayBtn.visible = false;


      video.element.onended = () => {
        this.replayBtn.visible = true;
      }

    }
  }

  refreshVideoSize(video) {
    if (!video.parent) {
      return;
    }
   
    video.width = video.element.videoWidth;
    video.height = video.element.videoHeight;
    const sx = video.parent.width / video.element.videoWidth;
    const sy = video.parent.height / 2 / video.element.videoHeight;


    console.log('sx: ', sx);
    console.log('sy: ', sy);


    video.setScaleXY(Math.min(sx, sy));

    video.x = - video.width / 2 * video.scaleX;
    video.y = - video.height / 2 * video.scaleY;

  }

  playHotZoneItemSA() {
    const arr = this.hotZoneArr;
    console.log('in showHotZonePic arr: ', arr);
    if (!arr || arr.length == 0) {
      return;
    }

    console.log('in showHotZonePic 1');

    let index = 0;
    const showOneHotZone = () => {

      console.log(' in showOneHotZone')
      if (index > arr.length - 1) {
        this.showWriteBtn();
        return;
      }

      
      const {data} = arr[index];
      if (data.gIdx == '0' || data.gIdx == '2' || data.gIdx == '3') {

        this.showHotZonePic(arr[index]);

        if (data.gIdx == '0') {
          this.lastHotZoneItem = arr[index]; //记录最后一个显示item 后面要替换
        }

        if (data.audio_url) {
          this.playAudio(data.audio_url, true, () => {

            index ++;
            showOneHotZone();
          })
        } else {
          index ++;
          showOneHotZone();
        }


      } else {
        index ++;
        showOneHotZone();
      }
    }

    showOneHotZone();
  }


  lastHotZoneItem;
  playHotZoneItemSC() {

    const arr = this.hotZoneArr;
    console.log('in showHotZonePic arr: ', arr);
    if (!arr || arr.length == 0) {
      return;
    }

    console.log('in showHotZonePic 1');

    let index = 0;
    const showOneHotZone = () => {

      console.log(' in showOneHotZone')
      if (index > arr.length - 1) {

        return;
      }

      
      const {data} = arr[index];
      if (data.gIdx == '0' || data.gIdx == '1') {

        this.showHotZonePic(arr[index]);

        if (data.gIdx == '0') {
          this.lastHotZoneItem = arr[index]; //记录最后一个显示item 后面要替换
        }

        if (data.audio_url) {
          this.playAudio(data.audio_url, true, () => {

            index ++;
            showOneHotZone();
          })
        } else {
          index ++;
          showOneHotZone();
        }


      } else {
        index ++;
        showOneHotZone();
      }
    }

    showOneHotZone();

  }

  showWriteBtn() {
    if (this.writeBtn) {
      this.writeBtn.visible = true;

      this.writeBtn.alpha = 0;
      tweenChange(this.writeBtn, {alpha: 1}, 1);
    }
  }

  showSmallTitle(data) {

    const imgObj = this.images.get(data.title_pic_url);
    this.lastHotZoneItem.init(imgObj);
    this.showHotZonePic(this.lastHotZoneItem);


    if (data.title_audio_url) {
      this.playAudio(data.title_audio_url, true)
    }

  }

  showHotZonePic(item) {
    console.log('item: ', item);
    item.visible = true;
    item.alpha = 0;

    tweenChange(item, {alpha: 1}, 0.5);
  }

  

  showSubmit() {
    if(this.submitBtn){
      this.submitBtn.visible = true;
      this.submitBtn.alpha = 1;
      this.submitBtn.shadowSpr.visible = true;
      this.submitBtn.shadowSpr.alpha = 1;
    }
  }
  
  hideSubmit() {
    if(this.submitBtn){
      this.submitBtn.visible = false;
      this.submitBtn.alpha = 0;
      this.submitBtn.shadowSpr.visible = false;
      this.submitBtn.shadowSpr.alpha = 0;
    }
  }

  removeSubmit() {
    if(this.submitBtn){
      this.submitBtn.parent.removeChild(this.submitBtn);
      this.submitBtn.shadowSpr.parent.removeChild(this.submitBtn.shadowSpr);

      this.submitBtn = null;
    }
  }


  testInput() {
   
    const tmpRect = this.sentenceEmptyArr[0].getBoundingBox();

    const svBox = this.scrollView.getBoundingBox();

   
    const x = svBox.x +  tmpRect.x * this.mapScale;
    const y = svBox.y + tmpRect.y * this.mapScale;
    const width = tmpRect.width * this.mapScale;
    const height = tmpRect.height * this.mapScale;
    const rect = {x, y, width, height};



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

    
    // const shape = new ShapeRectNew();
    // shape.setSize(200, 200, 1);
    // shape.fillColor = '#0000ff'
    // shape.x = 500;
    // shape.y = 500;
    // this.topArr.push(shape);

     
  
  }

  inputView;
  showInputView(style, rect, value, cb) {
    if (!this.inputView) {
      this.inputView = new InputView();
      this.inputView.isShowScroll = true;
    }

    const inputView = this.inputView;

    if (inputView.callback) {
      inputView.onblur();
    }

    inputView.show();

    inputView.x = rect.x  / this.canvasScale ;  // this.canvasWidth / 2;
    inputView.y = rect.y / this.canvasScale ; // this.canvasHeight / 2;
    inputView.width = rect.width / this.canvasScale ;
    inputView.height = rect.height / this.canvasScale ;
    inputView.text = value;
    inputView.callback = cb;
    inputView.setStyle(style);
    

    inputView.refreshInputStyle();
  }

  hideInputView() {
    if (!this.inputView) {
      return;
    }
    this.inputView.hide();
  }



  relink() {

    const progress = this.getPageData('progress');

    if (this.isTeacher) {
      if (progress != null) {
        this.gameStart();
        return;
      }
      return;
    }


    if (progress == '1') {

      this.gameStart();

      const resultData = this.getStoreData('resultData')
      if (resultData) {
        this.initResultView(resultData);
        return;
      }

      return;
    }

    // if (progress == '2' || progress == '3') {
    //   const submitCount = this.getPageData('submitCount')
    //   this.submitCount = submitCount;
    //   this.checkShowSubTemplateOne();
    //   return;
    // }
   
  }


  maskPic;
  initMaskPic() {
    const bgUrl = this.data.contentObj.bg_url;  
    console.log('bgUrl', bgUrl);
    
    const maskPic = this.getMySprite(bgUrl);
    const sx = this.canvasWidth / maskPic.width;
    const sy = this.canvasHeight / maskPic.height;
    const s = Math.max(sx, sy);
    maskPic.setScaleXY(s);
    maskPic.x = this.canvasWidth / 2;
    maskPic.y = this.canvasHeight / 2;

    if (this.isTeacher) {
      maskPic.visible = false;
    }

    this.maskPic = maskPic;
  }


  getMySprite(resName, isSetScale = true) {
    const spr = new MySprite();
    spr.init(this.images.get(resName))
    if (isSetScale) {
      spr.setScaleXY(this.mapScale);
    }
    return spr;
  }


  setRectRight(data) {

    console.log("in setRectRight : ", data);

    for (let i=0; i<this.hotZoneArr.length; i++) {
      this.hotZoneArr[i].result = data[i];
      if (data[i] && data[i].right) {
        this.hotZoneArr[i].isRight = true;
      } else {
        this.hotZoneArr[i].isRight = false;
      }
    }
  }

  resultLayer;
  resultPanel;
  moreBtn;
  initResultView(data = null) {


    if (data) {
      console.log('initResultView data : ', data)
      this.setRectRight(data);
    } else {
      const resultData = this.getResultData();
      this.userResultData = resultData;
      this.sendResult();
      this.setStoreData('resultData', resultData);
    }


    const resultLayer = new MySprite()
    resultLayer.x = this.canvasWidth / 2;
    resultLayer.y = this.canvasHeight / 2;
    

    const bg = new MySprite();
    bg.init(this.images.get("result_bg"))
    bg.x = 0
    bg.y = 0;
    bg.setScaleXY(this.mapScaleMax);
    resultLayer.addChild(bg);

    const bgItem = new MySprite();
    bgItem.init(this.images.get("result_bg_item"));
    bg.addChild(bgItem);

    const panelOffY = 0 //-50 * this.mapScale;
    const panel = new MySprite();
    panel.init(this.images.get("result_panel"));
    panel.setScaleXY(this.mapScale);
    panel.y = panelOffY;
    resultLayer.addChild(panel, 1);

    const panelItem = new MySprite();
    panelItem.init(this.images.get("result_panel_item"));
    panelItem.y = -600;
    panel.addChild(panelItem);

    const itemLabel = new RichText();
    itemLabel.fontSize = 52;
    // itemLabel.y = 5;
    itemLabel.width = panelItem.width;
    itemLabel.fontColor = '#ffffff'
    itemLabel.fontName = 'Aileron-Black';
    itemLabel.text = 'Check'
    itemLabel.y = 10;
    itemLabel.textAlign = 'center';
    panelItem.addChild(itemLabel, 5);

    const panelShadow = new MySprite();
    panelShadow.init(this.images.get("result_panel_shadow"));
    // panelShadow.setScaleXY(this.mapScale);
    panelShadow.y = ( panel.height / 2 - 20 );
    panel.addChild(panelShadow);

    const btn = new MySprite();
    btn.init(this.images.get("big_btn"));
    btn.setScaleXY(this.mapScale);
    btn.y = panel.y + ( panel.height / 2 + 120 ) * panel.scaleY;
    // resultLayer.addChild(btn, 2);
    // this.moreBtn = btn;

    const btnShadow = new MySprite();
    btnShadow.init(this.images.get("big_btn_shadow"));
    btnShadow.setScaleXY(this.mapScale);
    btnShadow.y = btn.y + 30 * this.mapScale;
    // resultLayer.addChild(btnShadow);


    const btnLabel = new Label();
    btnLabel.fontSize = 64;
    btnLabel.fontName = 'Aileron-Black';
    btnLabel.textAlign = 'center';
    btnLabel.text = '更多练习';
    btnLabel.y = 5;
    btnLabel.fontColor = '#ffffff';
    btn.addChild(btnLabel, 3);

    

    this.topArr.push(resultLayer);
    
    this.resultPanel = panel;
    this.resultLayer = resultLayer;



    this.initResultSentence();

 

  }

  getResultData() {
    const dataArr = [];
    for (let i=0; i<this.hotZoneArr.length; i++) {
      const result = this.hotZoneArr[i].result;
      result.userAnswer = this.hotZoneArr[i].label?.text || '';
      dataArr.push(result);
    }
    return dataArr;
  }



  initResultSentence() {

    const resultSv = new ScrollView();
    resultSv.setShowSize(this.resultPanel.width, this.resultPanel.height * 0.85);
    resultSv.setBgColor("#3e9e33");
    resultSv.x = -this.resultPanel.width / 2;
    resultSv.y = -this.resultPanel.height / 2 + 120;
    resultSv.setScrollBarSize(20 * this.mapScale, 5);
    // resultSv.setContentScale(this.mapScale);

    this.resultPanel.addChild(resultSv);
    this.resultSv = resultSv;

    console.log('hotZoneArr: ', this.hotZoneArr);

    const tmpLabel = new Label();
    tmpLabel.fontSize = 48;
    tmpLabel.fontColor = '#ffffff'
    tmpLabel.fontName = 'DroidSansFallback';


    let baseY = 0 //-500;
    for (let i=0; i<this.hotZoneArr.length; i++) {

      const result = this.hotZoneArr[i].result;

      const richText = new RichText();
      richText.disH = 5;
      // richText.x = -this.panel.width / 2 * 0.9
      richText.x = 0.05 * this.resultPanel.width;
      richText.y = baseY + 80;
   
      richText.fontSize = 48;
      richText.width = this.resultPanel.width * 0.9;
      richText.fontColor = '#ffffff'
      richText.fontName = 'DroidSansFallback';
      richText.text = result.userAnswer;

      // this.resultPanel.addChild(richText, 1)



      // const rect = richText.getBoundingBox();
      // richText.refreshSize();

      tmpLabel.text = richText.text;
      tmpLabel.refreshSize();
      let rectW = tmpLabel.width < 100 ? 100 : tmpLabel.width;

      const rect = {x: richText.x, y: richText.y, width: rectW, height: richText.fontSize};

      const addW = 18
      rect.width += addW;
      rect.height += 16;
      // rect.x += addW / 2;
      const colorRect = new ShapeRectNew();
      colorRect.setSize(rect.width, rect.height, 10);
      // colorRect.alpha = 0.3;
     
      colorRect.fillColor = '#007b3e'
      const offX = 9;
      colorRect.x = rect.x // + offX;
      colorRect.y = rect.y - rect.height / 2;
      // colorRect.alpha = 0.5;
      resultSv.addItem(colorRect);
      resultSv.addItem(richText);



      baseY = richText.y + richText.getAreaHeight();
      if (result.isAi) {
        colorRect.alpha = 0;

        const infoBg = new ShapeRectNew();
        // infoBg.init(this.images.get("info_bg"));
        infoBg.setSize(1838, 120, 60);
        infoBg.fillColor = '#3b962e';
        infoBg.y = baseY //+ 50;
        infoBg.x = (this.resultPanel.width - infoBg.width) / 2//* this.mapScale;
        // infoBg.x = this.resultPanel.width / 2 //* this.mapScale;
        resultSv.addItem(infoBg);
        // this.resultPanel.addChild(infoBg);
        // baseY += 130;

        const infoIcon = new MySprite();
        infoIcon.init(this.images.get("ai_icon"));
        infoIcon.x =  100;
        infoIcon.y = 60;
        infoBg.addChild(infoIcon);


        this.addResultLabelCircle(richText, result);
        const tmpH = this.getInfoLabelLayer(infoBg, result);
        if (tmpH < 60) {
          infoBg.visible = false;
        } else {
          baseY += tmpH;
          infoBg.height = tmpH;
          resultSv.refreshContentSize();
        }
   


      } else if (!this.hotZoneArr[i].isRight) {
        colorRect.fillColor = '#d71818'

        const infoBg = new MySprite();
        infoBg.init(this.images.get("info_bg"));
        infoBg.y = baseY + 50;
        infoBg.x = this.resultPanel.width / 2 //* this.mapScale;
        resultSv.addItem(infoBg);
        // this.resultPanel.addChild(infoBg);
        baseY += 130;

        const infoIcon = new MySprite();
        infoIcon.init(this.images.get("info_icon"));
        infoIcon.x = -infoBg.width / 2 + 100;
        infoBg.addChild(infoIcon);

        const infoLabel = new RichText();
        infoLabel.x = infoIcon.x + 50;
        infoLabel.fontSize = 48;
        infoLabel.y = 5;
        infoLabel.width = infoBg.width;
        infoLabel.fontColor = '#ffe9b1'
        infoLabel.fontName = 'Aileron-Black';
        infoLabel.text = this.hotZoneArr[i].result?.info || '';
        infoBg.addChild(infoLabel);

      } else {
        const labelAnswer = this.getFillLabel();
        labelAnswer.fontSize = 48;
        labelAnswer.fontColor = '#ffffff'
        labelAnswer.fontName = 'Aileron-Black';
        labelAnswer.text =  this.hotZoneArr[i].result?.info || '';
        labelAnswer.setScaleXY(1);
        labelAnswer.textAlign = 'center';

        labelAnswer.refreshSize();
        labelAnswer.x = colorRect.width / 2;
        labelAnswer.y = colorRect.height / 2;

        // colorRect.addChild(labelAnswer);
      }


      if (i != this.hotZoneArr.length - 1) {
        const line = new MySprite();
        line.init(this.images.get("line"));
        line.x = this.resultPanel.width / 2;
        line.y = baseY + 30;

        resultSv.addItem(line);
        // this.resultPanel.addChild(line);

        baseY = line.y
      }


    }
    
    console.log('this.resultSv.height: ', this.resultSv.heigth);
    console.log('this.resultSv.box height: ', this.resultSv.getBoundingBox().height);
    
  }

  getInfoLabelLayer(infoBg, result) {

    const {resultTextArr, iconData} = result;

    const arr = [];
    for (let k in iconData) {
      iconData[k].index = k ;
      arr.push(iconData[k])
    }
    
    const layer = new MySprite();

    let baseIndex = 0;
    let tmpH = 40;
    for (let i=0; i<arr.length; i++) {

      const circle = new ShapeCircle();
      circle.setRadius(30);
      circle.x = 200;
      circle.y = tmpH + 20;
      circle.fillColor = '#dcc077'
      infoBg.addChild(circle);

      const label = new Label();
      label.text = (i+1).toString();
      label.fontColor = '#ffffff';
      label.textAlign = 'center';
      label.fontName = 'Aileron-Bold';
      label.y = 3;
      circle.addChild(label);

      const infoLabel = new RichText();
      infoLabel.topH = 0;
      infoBg.addChild(infoLabel);
  
      infoLabel.x = 230;
      infoLabel.fontSize = 48;
      infoLabel.y = tmpH + 20;
      infoLabel.width = infoBg.width * 0.8;
      infoLabel.fontColor = '#ffe9b1'
      infoLabel.fontName = 'Aileron-Black';
      infoLabel.text = arr[i].dataArr[0].reason;

      tmpH = infoLabel.y + infoLabel.getAreaHeight();

      // const rect = lastRect.rect;
      // rect.x -= rect.width;
      // rect.y -= rect.height / 2;
      // const colorRect = this.getColorRect(rect);
      // colorRect.alpha = 0.5;
      // // colorRect.y -= rect.height;
      // // infoLabel.addChild(colorRect);

      // const circle = new ShapeCircle();
      // circle.setRadius(20);
      // circle.fillColor = '#dcc077';
      // circle.x = rect.x + rect.width;
      // circle.y = rect.y;
      // infoLabel.addChild(circle);

      // const label = new Label();
      // label.textAlign = 'center';
      // label.fontColor = '#ffffff';
      // label.fontSize = 30;
      // label.text = (i + 1).toString()
      // circle.addChild(label);


    }

    return tmpH

    // const infoLabel = new RichText();
    // infoBg.addChild(infoLabel);

    // infoLabel.x = infoIcon.x + 50;
    // infoLabel.fontSize = 48;
    // infoLabel.y = 5;
    // infoLabel.width = infoBg.width;
    // infoLabel.fontColor = '#ffe9b1'
    // infoLabel.fontName = 'Aileron-Black';
    // infoLabel.text = this.getOneAiResultText(result);//  this.hotZoneArr[i].result?.info || '';
    // this.addResultLabelCircle(infoLabel, result);

  }

  getOneAiResultText(result) {

    const {resultTextArr} = result;
    let curText = '';
    for (let i=0; i<resultTextArr.length; i++) {
      curText += resultTextArr[i].text + '';
    }
    console.log(' in getOneAiResultText ', resultTextArr);
    return curText;
  }

  addResultLabelCircle(infoLabel, result) {
    const {resultTextArr, iconData} = result;

    let baseIndex = 0;
    for (let i=0; i<resultTextArr.length; i++) {
      const curText = resultTextArr[i].text;
      // const rect = infoLabel.getSubTextRect(curText)?.rect;
      const rectGroup = infoLabel.getSubTextRectGroup(curText, baseIndex);
      if (!rectGroup) {
        continue;
      }
      
      console.log('~rectGroup: ', rectGroup);
      
      // const rectFirst = rectGroup[0];

      if (!rectGroup ||  rectGroup.length == 0) {
        continue;
      }

      const lastRect = rectGroup[rectGroup.length - 1];
      const key = lastRect.index + lastRect.text.length;

      console.log('~key: ', key);
      console.log('~rect: ', lastRect);
      console.log('iconData: ', iconData);
      if (!iconData[key]) {
        continue;
      }

      const rect = lastRect.rect;
      rect.x -= rect.width;
      rect.y -= rect.height / 2;
      const colorRect = this.getColorRect(rect);
      colorRect.alpha = 0.5;
      // colorRect.y -= rect.height;
      // infoLabel.addChild(colorRect);

      const circle = new ShapeCircle();
      circle.setRadius(20);
      circle.fillColor = '#dcc077';
      circle.x = rect.x + rect.width;
      circle.y = rect.y;
      infoLabel.addChild(circle);

      const label = new Label();
      label.fontName = 'Aileron-Bold';
      label.textAlign = 'center';
      label.fontColor = '#ffffff';
      label.fontSize = 30;
      label.text = (i + 1).toString()
      label.y = 3;
      circle.addChild(label);

      // colorRect.addChild(circle);
    }
  }

  getColorRect(rect) {

    const colorRect = new ShapeRectNew();
    colorRect.setSize(rect.width, rect.height, 1);
   
    colorRect.fillColor = Math.random() < 0.5 ? '#ff0000' : '#00ff00'
    // const offX = 13; 
    colorRect.x = rect.x // + offX;
    colorRect.y = rect.y // -rect.height / 2;
    // console.log('rect.height: ', rect.height);
    // colorRect.alpha = 0;
    return colorRect;
  }


  submitBtn;
  btnArr = [];
  btnDisH = 120;
  initBtn() {

    this.topArr = [];

    const btnArr = [];
    let arr =  JSON.parse(JSON.stringify(this.sentenceArr)) ;
    arr = randomSortByArr(arr);
    if (!arr) {
      return;
    }
    const disW = 400 * this.mapScale;
    const disH = this.btnDisH * this.mapScale;
    const tmpLen = arr.length > 5 ? 5 : arr.length;
    let baseX = this.canvasWidth / 2 - (tmpLen - 1) * disW / 2
    let baseY = this.canvasHeight / 2 - 380 * this.mapScale;
    let col = 0;

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

      const btn = new MySprite();
      btn.init(this.images.get("btn"))
      btn.x = baseX + disW * col;
      btn.y = baseY;
      btn['baseX'] = btn.x;
      btn['baseY'] = btn.y;
      btn.setScaleXY(this.mapScale * 0.8);

      const btnBg = new MySprite();
      btnBg.init(this.images.get("btn_bg"))
      btnBg.x = btn.x;
      btnBg.y = btn.y;
      btnBg.setScaleXY(this.mapScale * 0.8);

      this.renderArr.push(btnBg);
      this.topArr.push(btn);

      this.addBtnLabel(btn, arr[i].answer);

      btnArr.push(btn);

      col ++ ;
      if (col % 5 == 0) {
        col = 0;
        baseY += disH;
      }
    }
 
    this.btnArr = btnArr;


    if (this.isTeacher) {
      this.initsendBtn();
      return;
    }


    const submitBtn = new MySprite();
    submitBtn.init(this.images.get("submit"));
    submitBtn.setScaleXY(this.mapScale);
    submitBtn.x = this.canvasWidth / 2 + 650 * this.mapScale;
    submitBtn.y = this.canvasHeight / 2 + 650 * this.mapScale;



    const submitShadow = new MySprite();
    submitShadow.init(this.images.get("submit_shadow"));
    submitShadow.setScaleXY(this.mapScale);
    submitShadow.x = submitBtn.x;
    submitShadow.y = submitBtn.y + 20 * this.mapScale;



    const submitOff = new MySprite();
    submitOff.init(this.images.get("submit_off"));
    submitOff.setScaleXY(this.mapScale);
    submitOff.x = submitBtn.x;
    submitOff.y = submitBtn.y + 5 * this.mapScale;


    submitBtn['baseY'] = submitBtn.y;
    submitBtn['offBtn'] = submitOff;
    submitBtn['shadowSpr'] = submitShadow;
    submitShadow['baseY'] = submitShadow.y;
    
    this.renderArr.push(submitShadow);
    this.renderArr.push(submitBtn);
    this.renderArr.push(submitOff);

    this.submitBtn = submitBtn;

    this.submitOff();
  }

  sendBtn;
  initsendBtn() {

    const panel = this.panel;

    const btn = new MySprite();
    btn.init(this.images.get("big_btn"));
    btn.setScaleXY(this.mapScale);
    btn.x = this.canvasWidth / 2;
    btn.y = panel.y + ( panel.height / 2 - 120 ) * panel.scaleY;
    this.sendBtn = btn;


    const btnShadow = new MySprite();
    btnShadow.init(this.images.get("big_btn_shadow"));
    btnShadow.setScaleXY(this.mapScale);
    btnShadow.x = btn.x;
    btnShadow.y = btn.y + 20 * this.mapScale;
    this.sendBtn.shadowSpr = btnShadow;

    const btnLabel = new Label();
    btnLabel.fontSize = 64;
    btnLabel.fontName = 'Aileron-Black';
    btnLabel.textAlign = 'center';
    btnLabel.text = 'Send';
    btnLabel.y = 5;
    btnLabel.fontColor = '#ffffff';
    btn.addChild(btnLabel, 3);

    this.renderArr.push(btnShadow);
    this.renderArr.push(btn);
  }


  submitOff() {
    this.submitBtn.offBtn.visible = true;

    this.submitBtn.visible = false;
    this.submitBtn.shadowSpr.visible = false;
  }

  submitOn() {

    // this.submitBtn.y = this.submitBtn.baseY;
    // this.submitBtn.scale = this.mapScale;

    // this.submitBtn.shadowSpr.alpha = 1;
    // this.submitBtn.shadowSpr.y = this.submitBtn.shadowSpr.baseY;
    

    this.submitBtn.visible = true;
    this.submitBtn.shadowSpr.visible = true;

    this.submitBtn.offBtn.visible = false;
  }


  addBtnLabel(btn, text) {
    console.log('text:  ', text);

    const label = new Label();
    label.fontSize = 64;
    label.fontName = 'Aileron-Black';
    label.textAlign = 'center';
    label.text = text;
    // label.x = this.canvasWidth / 2;
    label.y = -2;
    label.fontColor = '#f1e4c2';
    btn.addChild(label);
    btn.text = text;
    return label;
  }

  sentenceEmptyArr;
  initSentence() {

    const row = Math.floor( (this.btnArr.length - 1) / 5 ) + 1;
    const subH = row * this.btnDisH ;

    const sv = new ScrollView();
    // sv.setShowSize(this.panel.width, 900 - subH);
    // sv.x = -this.panel.width / 2;
    // sv.y = -395 + subH;
    // sv.setBgColor('#faf7ee')
    // // sv.setMapScale(this.mapScale);
    // // sv.content.setScaleXY(1/this.mapScale);
    // sv.setScrollBarSize(20 * this.mapScale, 5)
    // // this.renderArr.push(sv);
    // // sv.setScaleXY(this.mapScale);
    // // sv.x = 0;
    // // sv.y = 200;
    // sv.setContentScale(this.mapScale);

    // this.panel.addChild(sv);
    // this.scrollView = sv;


    
    this.sentenceEmptyArr = [];
    
    const arr = this.sentenceArr;
    // const arr = this.sentenceArr.concat(this.sentenceArr);
    if (!arr) {
      return;
    }
    const baseX = this.panel.width / 2 - 1000 ;
    let curY = 70 // this.canvasHeight / 2 - 110 * this.mapScale;
    const disH = 70 * this.mapScale;
    for (let i=0; i<arr.length; i++) {
      const richText = this.getSentenceLabel();
      richText.x = baseX;
      richText.y = curY;
      richText.text = arr[i].text;

      const rect = richText.getSubTextRect('____________________');
      const colorRect = new ShapeRectNew();
      rect.height += 30;
      colorRect.setSize(rect.width, rect.height, 1);
     
      colorRect.fillColor = '#ff0000'
      const offX = 13;
      colorRect.x = rect.x + offX;
      colorRect.y = -rect.height / 2;
      console.log('rect.height: ', rect.height);
      colorRect.alpha = 0;

  

      richText.addChild(colorRect);
      this.sentenceEmptyArr.push(colorRect);

      curY += richText.getAreaHeight() * this.mapScale + disH;

      richText['data'] = arr[i];


      sv.addItem(richText);

      // this.renderArr.push(richText);
      colorRect.ctx = colorRect.parent.ctx;


    }
    

  }

  getFillLabel() {
    const label = new RichText();
 
    label.fontSize = 56;
    label.fontColor = '#000000'
    label.fontName = 'Aileron-Bold';
    // label.setScaleXY(this.mapScale);
    
    return label;
  }

  getSentenceLabel() {

    const richText = new RichText();
    richText.disH = 0;
 
    richText.fontSize = 56;
    richText.width = 2000 / this.mapScale
    richText.fontColor = '#000000'
    richText.fontName = 'DroidSansFallback';
    richText.setScaleXY(this.mapScale);
    
    return richText;

  }

  changeBtnOff() {

    for (let i=0; i<this.btnArr.length; i++) {
      if (this.btnArr[i].visible) {
        this.btnArr[i].init(this.images.get('btn_off'));
        this.btnArr[i].isOff = true;
      }
    }
    
  }

  changeBtnOn() {

    for (let i=0; i<this.btnArr.length; i++) {
      if (this.btnArr[i].visible) {
        this.btnArr[i].init(this.images.get('btn'));
        this.btnArr[i].isOff = false;
      }
    }
    
  }





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

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

    }
  }


  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) {
      audio.play();
    }
  }
















  panel;

  initBg() {

    const colorBg = this.getMySprite("bg");
    colorBg.setScaleXY(this.mapScaleMax);
    this.renderArr.push(colorBg);
    colorBg.x = this.canvasWidth / 2;
    colorBg.y = this.canvasHeight / 2;

   
    const title = new Label();
    title.fontSize = 76 * this.mapScale;
    title.fontName = 'Aileron-Bold';
    title.textAlign = 'left';
    // title.setMaxSize(this.canvasWidth * 0.9);
    title.x = 240;
    title.y = 100 * this.mapScale;
    title.fontColor = '#3e9b31';
    title.text = this.data.contentObj.title || "";
    title.refreshSize();
    this.renderArr.push(title);



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

   


    const subH = title.fontSize;
    const url = this.data.contentObj.bgItem?.url;
    if (url) {
      const bg = new MySprite();
      bg.init(this.images.get(url));

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

      bg.setScaleXY(this.mapScale);
      bg.x = this.canvasWidth / 2;
      bg.y = this.canvasHeight / 2 + subH;
      
      bg['data'] = this.data.contentObj.bgItem;
      this.bg = bg;
      this.renderArr.push(bg);
    }
 


  }






  okBtnClick() {
    this.checkPanel.visible = false;
    this.removeSubmit();
    // this.appRef.tick();

    this.canTouch = false;
    setTimeout(() => {
      // this.hideSubmit();
      this.convertCanvasToImage();
      // this.hideSubmit();
      setTimeout(() => {
        this.setAnswerData(() => {
          this.initResultView();
          this.canTouch = true;
        });

       

      }, 500);
    }, 500);
 
  }

  cancelBtnClick() {
    this.checkPanel.visible = false;

  }


  curMoveItem = null;
  downFlag = false;
  mapDown(event) {


    if (!this.canTouch) {
      return;
    }

    if (this.videoMask && this.videoMask.visible) {

      if (this.videoCloseBtn) {
        if (this.checkClickTarget(this.videoCloseBtn)) {
          this.videoCloseBtnClick();
          return;
        }
      }
  
      if (this.replayBtn && this.replayBtn.visible) {
        if (this.checkClickTarget(this.replayBtn)) {
          this.replayBtnClick();
          return;
        }
      }

      return;
    }

    // 选择题区域 可见
    if (this.curAreaItem && this.curAreaItem.visible) {
      for (let i=0; i<this.optionItemArr.length; i++) {
        if (this.checkClickTarget(this.optionItemArr[i])) {
          this.optionItemClick(this.optionItemArr[i]);
          return;
        }
      }

      if (this.checkClickTarget(this.videoBtn)) {
        this.videoBtnClick();
        return;
      }
    } else {

      if (this.checkClickTarget(this.answerRect)) {
        this.answerRectClick();
        return;
      }
      if (this.checkClickTarget(this.writeBtn)) {
        this.writeBtnClick();
        return;
      }
      
  
    }
   

   
    

  }




  mapMove(event) {

    if (event) {
      event.preventDefault()
    }

   
  }


  mapUp(event) {



  }

  writeBtnClick() {

    const courseware = window['courseware'];
    if (!courseware) {
      return;
    }
    courseware.activeWhiteBoard((data) => {
      // TODO 公式编辑器返回的结果
      console.log('activeWhiteBoard data: ', data);
    });
  }

  videoBtnClick() {

    this.videoMask.visible = true;
    this.videoBg.visible = true;
    
    const video = this.curVideo;
    video.element.currentTime = 0.01;
    video.element.play();
  }


  answerRectClick() {
    console.log('in answerRectClick');

    const courseware = window['courseware'];
    if (!courseware) {
      return;
    }

    courseware.activeFormulaBoard((data) => {
      // TODO
      console.log('in activeFormulaBoard data 1 : ', data);
      if (typeof (data) == 'string') {
        data = JSON.parse(data);
      }

      console.log('in activeFormulaBoard data 2 : ', data);

      this.setShortAnswerData(data);

    });

    // const data = {
    //   formulaSrc: 'http://staging-teach.cdn.ireadabc.com/82f0ecacdc80cbb50c1a229cdee253c4.png',
    //   formula:"\\sqrt {777}+\\sqrt {444}"
    // }

    // this.setShortAnswerData(data);
  }

  setShortAnswerData(data) {
    const {formulaSrc, formula} = data;


    const labelPic = this.answerLabelPic;
    labelPic.load(formulaSrc).then(img => {
      const sx = (this.answerRect.width * this.answerRect.scaleX - 20) / labelPic.width;
      const sy = this.answerRect.height * this.answerRect.scaleY / labelPic.height;
      const s = Math.min(sx, sy);
      labelPic.setScaleXY(s);
      labelPic.x = labelPic.width / 2 * labelPic.scaleX + 10;
      labelPic.y = this.answerRect.height * this.answerRect.scaleY / 2;
    });


    if (formula && false) {

      this.changeAnswerBg('rightPic');
    } else {

      this.changeAnswerBg('wrongPic');

      setTimeout(() => {

        // this.changeChoiceArea(this.data.contentObj.choice_obj);      
      }, 2000);
    }
  }

  changeBase64ToPicUrl(base64Data) {

    var arr = base64Data.split(','), mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while(n--){
        u8arr[n] = bstr.charCodeAt(n);
    }
    var obj = new Blob([u8arr], {type:mime});
    var fd = new FormData();

    fd.append("file", obj, "jm_math.png");

    // 上传截图
    this.http.post(this.uploadUrl, fd).subscribe((res) => {
      // 存储服务器的截图url
      if (res['url']) {
        console.log('res url: ', res['url']);
        
      } else {

      }
    });


  }


  replayBtnClick() {
    if (this.curVideo) {
      this.curVideo.element.play();
      this.replayBtn.visible = false;
    }
  }

  videoCloseBtnClick() {
    console.log("in videoCloseBtnClick");
    this.videoBg.visible = false;
    this.videoMask.visible = false;

  
    if (this.curVideo) {
      this.curVideo.element.pause();
    }
    if (this.curOpItem) {
      this.changeChoiceArea(this.curOpItem.data);
    }
    if (this.curVideo && !this.videoBtn.visible) {
      this.videoBtn.visible = true;
    }
  }

  cleanSmallTitle() {

    this.curAreaItem.visible = false;
    this.curAreaItem.removeChildren();

    removeItemFromArr(this.renderArr, this.curAreaItem);
    removeItemFromArr(this.renderArr, this.answerRectNode);
    removeItemFromArr(this.renderArr, this.answerQuesPic)

    if (this.videoBtn) {
      this.videoBtn.visible = false;
    }
  }

  curOpItem;
  optionItemClick(opItem) {
    console.log('opItem: ', opItem);
    const data = opItem.data;
    this.curOpItem = opItem;
    this.changeAllOpItem();
    if (data.is_right) {
      this.optionRight(opItem);
    } else {
      this.optionWrong(opItem);
    }
  }

  optionRight(opItem) {
    this.changeOpItemBg(opItem, 'rightPic');

  }

  optionWrong(opItem) {
    this.changeOpItemBg(opItem, 'wrongPic');

 

    this.canTouch = false;
    setTimeout(() => {
      this.canTouch = true;

      if (this.data.contentObj.ques_type == this.TYPE_SHORT_ANSWER) {
        this.cleanSmallTitle();
        this.changeAnswerArea();
        return;
      }

      if (opItem.data.video_url) {
        this.showVideo(opItem);
      } else {
        this.callTeacher();
      }

    }, 2000);
  }

  callTeacher() {
    this.changeChoiceArea(this.data.contentObj);
  }

  showVideo(opItem) {
    const {data} = opItem;
    this.videoMask.visible = true;
    this.videoBg.visible = true;

    this.initVideoPlayer(data);
  }

  hideVideo() {
    this.videoMask.visible = false;
    this.videoBg.visible = false;
  }

  
  changeAllOpItem() {
    for (let i=0; i<this.optionItemArr.length; i++) {
      this.changeOpItemBg(this.optionItemArr[i], 'normalPic');
    }
  }

  changeOpItemBg(opItem, res) {
    opItem[opItem.curRes].visible = false;
    opItem.curRes = res;
    opItem[opItem.curRes].visible = true;
  }

  changeAnswerBg(res) {

    const node = this.answerRectNode;
    node[node.curRes].visible = false;
    node.curRes = res;
    node[node.curRes].visible = true;
  }


  moreBtnClick() {
    // this.setPageData('progress', '2', false);
    // this.setPageData('submitCount', this.submitCount);
    this.checkShowSubTemplateOne();
    this.isUpdateStop = true;

  }

  checkShowSubTemplateOne() {

    // this.showSubTemplate(0);

    console.log(' in checkShowSubTemplateOne')
    const progress = this.getPageData('progress');

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



    if (progress == '2') {
      if (this.submitCount == 1) {
        this.showSubTemplate(1);
        this.sendSubTempIsShowMore(1, true);
      } else {
        this.showSubTemplate(0);
        this.sendSubTempIsShowMore(0, true);
      }

      return;
    }

    if (progress == '3') {

      let index;
      if (this.submitCount == 1) {
        index = 0;
        this.hideSubTemplate(1);
      } else {
        index = 1;
        this.hideSubTemplate(0);

      }

      this.showSubTemplate(index);
      this.sendSubTempIsShowMore(index, false);

    }

  }

  sendSubTempIsShowMore(index, isShowMore) {

    setTimeout(() => {
      const divArr = this.iframeContent.nativeElement.children;
      const iframecont = divArr[index].children[0];
      const data =  { msg: 'success', isShowMore};
      iframecont.contentWindow.postMessage({ action: 'is_show_more', data: JSON.stringify(data) }, '*');
      console.log(' post msg is_show_more ')
    }, 1000);
 
  }


  btnDown(btn) {
    this.curMoveItem = btn;
  }

  addLabelMask(target, label) {
    const box = target.getBoundingBox();


    // const mask = new ShapeRect();
    // mask.setSize(400, 400);
    // mask.fillColor = '#ff0000';

    // // const mask = new MySprite();
    // // mask.init(this.images.get("mask"))
    // // mask.x = rect.x;
    // // mask.y = rect.y;
    // // const sx = rect.width / mask.width;
    // // const sy = rect.height / mask.height;
    // // mask.scaleX = sx;
    // // mask.scaleY = sy;

    // // this.scrollView.addItem(mask);

    // // label.addMaskSpr(mask);
    // // mask.x = 200;
    // // mask.y = 200;



    // // const label1 = new MySprite();
    // // label1.init(this.images.get("btn_bg"))
    // // label1.setScaleXY(2);

    // const label1 = this.getFillLabel();
    // label1.text = 'aaaaaaaa a a a a a a a a a a a a a a ';
    // label1.x = 400;
    // label1.y = 400;
    // label1.width = mask.width;
    // label1.height = mask.height;
    // label1.textBaseline = 'top';
    // // label1.setMaxSize(rect.width);


    // this.renderArr.push(mask);

    // this.renderArr.push(label1);
    


    // // mask.setMaskType("destination-in");
    // // // label1.addMaskSpr(mask)
    // // mask.addMaskSpr(label1);
    // label1.addMaskSpr(mask);

    label.width = box.width;
    label.height = box.height;
    label.x = box.width / 2;
    label.y = box.height / 2;

    const rect = new ShapeRect();
    rect.setSize(box.width, box.heigth);
    label.addMaskSpr(rect);
  }
  
  inputFontSize = 40;
  emptyRectDown(targetRect) {

    if (!targetRect.label) {
      const label = this.getFillLabel();
      label.fontSize = this.inputFontSize;
      label.disH = 0;
      label.offW = 0;
      label.textBaseline = 'top'
      label.width = targetRect.width;
      label.fontSize *= (this.bg.scaleX);
      // targetRect.label.x = ( targetRect.width / 2  ) 
      targetRect.label = label;
      targetRect.addChild(targetRect.label);

      this.addLabelMask(targetRect, label);
    }

    if (targetRect.label.isDefault) {
      targetRect.label.text = '';
      targetRect.label.fontColor = '#000000';
      targetRect.label.isDefault = false;
    }

    if (true) {

      const scale = 1 // this.mapScale;

      let tmpRect = targetRect.getBoundingBox();

      const svBox = this.scrollView.getBoundingBox();
    
      const x = svBox.x + tmpRect.x * scale;
      const y = svBox.y + tmpRect.y * scale;
      const width = tmpRect.width * scale;
      const height = tmpRect.height * scale;
      const rect = {x, y, width, height};

      const style = {
        'font-size' : this.inputFontSize / this.canvasScale * this.bg.scaleX + 'px',
        'color' : '#000000',
        'font-family' : 'Aileron-Bold',
        'line-height' : this.inputFontSize / this.canvasScale * this.bg.scaleX + 'px',
      }
      this.showInputView(style, rect, targetRect.label.text || '', (value) => {
        targetRect.label.text = value;
        this.checkShowSubmit();
      })
  
    }
  }


  checkPanel;
  okBtn;
  cancelBtn;
  showCheckPanel() {
    if (!this.checkPanel) {
      this.checkPanel = new MySprite();
      this.checkPanel.init(this.images.get("check_panel"));
      this.checkPanel.setScaleXY(this.mapScale);
      this.checkPanel.x = this.canvasWidth / 2;
      this.checkPanel.y = this.canvasHeight / 2;

      const label = new Label();
      label.text = '本题只能提交一次，确认提交吗？'
      label.textAlign = 'center';
      label.fontColor = '#ffffff';
      label.fontSize = 56 //* this.mapScale;
      label.fontName = 'Aileron-Black';
      label.y = -70;
      this.checkPanel.addChild(label);
      // label.x = this.checkPanel.width / 2;
      // label.y = this.checkPanel.height / 2;
  


      const offX = 300;
      const okBtn = new MySprite()
      okBtn.init(this.images.get("check_ok"));
      this.checkPanel.addChild(okBtn);
      okBtn.x = offX;
      okBtn.y = 130;
      this.okBtn = okBtn;

      const cancelBtn = new MySprite()
      cancelBtn.init(this.images.get("check_cancel"));
      this.checkPanel.addChild(cancelBtn);
      cancelBtn.x = -offX;
      cancelBtn.y = okBtn.y;
      this.cancelBtn = cancelBtn;



      this.renderArr.push(this.checkPanel);
    }
 
    this.checkPanel.visible = true;
  }

  submitBtnClick() {

    // this.submitCount ++;


    const btnBaseY =  this.submitBtn.y;
    const btnTargetY = btnBaseY + 5 * this.mapScale;

    const baseS = this.submitBtn.scaleX;
    const targetS = baseS * 0.95;
    const time = 0.07;

    this.canTouch = false;
    tweenChange(this.submitBtn, {y: btnTargetY, scaleX: targetS, scaleY: targetS}, time, ()=> {
      // tweenChange(this.submitBtn, {y: btnBaseY, scaleX: baseS, scaleY: baseS}, time)

      tweenChange(this.submitBtn, {y: btnBaseY, scaleX: baseS, scaleY: baseS}, time, () => {
        this.canTouch = true;
      })

      this.showCheckPanel();

      // this.submitOff();
      
      // const isAllRight = this.checkAnswer();

    
      // if (isAllRight || this.submitCount >= 2) {
      //   this.changeBtnOff();
      //   this.btnArr = [];

    


      //   delayCall(0.3, ()=> {
      //     this.initResultView();

      //     this.setPageData('progress', '2', false);
      //     this.setPageData('submitCount', this.submitCount);
      //     this.serverSendAnswer('4-1', this.resultAnswerArr);
      //   })
      // }

        

    })

    const shadow = this.submitBtn.shadowSpr;
    const shadowBaseY =  shadow.y //shadow['baseY'];
    const shadowTargetY = shadowBaseY - 15 * this.mapScale;
    tweenChange(shadow, {y: shadowTargetY, alpha: 0}, time, ()=> {
      shadow.y = shadowBaseY;
      shadow.alpha = 1;
      tweenChange(shadow, {y: shadowBaseY, alpha: 1}, time)
    })

    // this.addResultAnswer();

  }

  addResultAnswer() {

    console.log('this.data.contentObj.sentenceArr: ', this.data.contentObj.sentenceArr)
    console.log('this.sentenceEmptyArr: ', this.sentenceEmptyArr);

    const sentenceArr = this.data.contentObj.sentenceArr;
    const resultAnswer = [];
    for (let i=0; i<sentenceArr.length; i++) {
      const label = this.sentenceEmptyArr[i].label;
      const tmpData = {};
      tmpData['question'] = sentenceArr[i];
      tmpData['userAnswer'] = label.text;

      resultAnswer.push(tmpData);
    }

    this.resultAnswerArr.push(resultAnswer);

  }

  sendResult() {

    // if (this.userResultPic && this.userResultData) {

      const c = window['courseware'];
      if (!c) {
        return;
      }

      const duration = new Date().getTime() - this.localStartTime;
      c.sendAnswer({resultData: this.userResultData, resultPic: this.userResultPic || '', duration});
      
    // }




  }




  async setAnswerData(cb) {

    let isAllRight = true;
    for (let i=0; i<this.hotZoneArr.length; i++) {

      const data = this.hotZoneArr[i].data;
      console.log('data: ', data);

      let answer = this.hotZoneArr[i].label?.text || '';

      console.log('answer: ', answer);
      console.log('i: ', i);

      // answer = answer.replace(/\n/g," ");

      let result;
      if (data.selectType == 'ai') {
        result = await this.serverTest(answer);
        result.isAi = true;
      } else {


        result = await this.paperForCheck(data, answer, this.hotZoneArr[i].data.labelText)

      
         
        // result = checkAnswer(data.selectType, answer, this.hotZoneArr[i].data.labelText || null);
      }
     
     
      console.log('result: ', JSON.parse(JSON.stringify(result)) );

      this.hotZoneArr[i].result = result;


      if (!result.right) {
        // this.removeRectText( this.hotZoneArr[i] );
        isAllRight = false;
      } else {
        this.hotZoneArr[i].isRight = true;
        // this.showSentenceRight(this.hotZoneArr[i]);
      }
    }


    cb();
    // return isAllRight;
   
  }

  async paperForCheck(data, answer, labelText = null) {

    return new Promise((resolve, reject) => {

      console.log(' in greadPapersForCheck data: ', {type:data.selectType, blankWord: answer, word: labelText});


      window['courseware'].greadPapersForCheck({type:data.selectType, blankWord: answer, word: labelText}, res => {
        // res 需要toJSON
        console.log('in greadPapersForCheck res: ', res);
        if (res) {

          resolve(JSON.parse(res))
        } else {
          reject();
        }
      });

       
    })



  }


  async serverTest(text) {

    return new Promise((resolve, reject) => {

      const c = window['courseware'];
      if (!c) {
        console.error('not found window.courseware')
        reject();
        return;
      }
  
  
      if (text) {
  
        this.iconData = {};

        console.log(' greadPapersForText start')

        c.greadPapersForText(text, (res) => {

          console.log(' greadPapersForText end')

          const resData = JSON.parse(res);
          const sentsFeedback = resData.detail?.essayFeedback?.sentsFeedback
          let startIndex = 0;
          if (sentsFeedback) {
            for (let i=0; i<sentsFeedback.length; i++) {
              const {errorPosInfos, rawSent} = sentsFeedback[i];
              if (!errorPosInfos || !rawSent) {
                continue;
              }
              const baseIndex = text.indexOf(rawSent, startIndex);
  
              console.log('text: ', text);
              console.log('rawSent: ', rawSent);
              console.log('baseIndex: ', baseIndex);
              for (let j=0; j<errorPosInfos.length; j++) {
                const {reason, endPos} = errorPosInfos[j];
                this.addIconData(baseIndex + endPos, {reason});
              }

              startIndex = baseIndex;
            }
          }
          console.log('res : ', res);
          console.log('iconData : ', this.iconData);
  
          this.createResultTextArr(text);
          resolve({resultTextArr:this.resultTextArr, iconData: this.iconData, detail: resData.detail});
          // this.setComment(resData);
        })
      }

    });

  
    
  }

  iconData;
  addIconData(index, result) {
    if (!this.iconData) {
      this.iconData = {};
    }
  
    const key = index.toString();
    if (!this.iconData[key]) {
      this.iconData[key] = {dataArr: []};
    } 

    this.iconData[key].dataArr.push(result)
    
  }


  resultTextArr = [];
  createResultTextArr(text) {
    const iconKeys = Object.keys(this.iconData);
    iconKeys.sort((a, b) => {
      return Number(a) - Number(b);
    })

    this.resultTextArr = [];
    let curStartPos = 0;
    for (let i=0; i<iconKeys.length; i++) {
      const textData = this.iconData[iconKeys[i]];
      const endPos = Number(iconKeys[i]);
      textData['text'] = text.substring(curStartPos, endPos);
      this.resultTextArr.push(textData)

      curStartPos = endPos;
    }


    const textData = {dataArr: []}
    textData['text'] = text.substring(curStartPos)
    this.resultTextArr.push(textData)
    

    console.log('text: ',  text);
    console.log('resultTextArr: ', this.resultTextArr);
  }



  removeRectText(emptyRect) {

    this.showBtnByText(emptyRect.label.text);

    emptyRect.removeChild(emptyRect.label);
    // removeItemFromArr(this.renderArr, emptyRect.label);
    emptyRect.label = null;
  }

  showSentenceRight( emptyRect ) {

    if (!emptyRect.isRight) {
      emptyRect.isRight = true;
      const pos = {x: emptyRect.width / 2, y: emptyRect.height / 2};
      this.showRightParticle(emptyRect, pos)
    }
  
  }

  showRightParticle(emptyRect, point ) {
    const shapeW = 25 // * this.mapScale;
    const shapeH = 25 // * this.mapScale;
    showShapeParticle( 'rect', shapeW, shapeH, point, emptyRect, 20, 50, 180, 0.4);
  }


  showBtnByText(text) {
    for (let i=0; i<this.btnArr.length; i++) {
      if (this.btnArr[i].text == text) {
        this.btnArr[i].visible = true;
        return;
      }
    }
  }

 
  checkOnTarget() {

     
    for (let i = 0; i < this.sentenceEmptyArr.length; i++) {
      if (this.checkClickTargetSv(this.sentenceEmptyArr[i])) {

        this.playAudio('click', true);

        if (this.sentenceEmptyArr[i].isRight) {
          this.moveItemBack();
          return;
        }

        const tmpText = this.sentenceEmptyArr[i].label ? this.sentenceEmptyArr[i].label.text : '';

        const btnIndex = this.btnArr.indexOf(this.curMoveItem);
        const isBtn = btnIndex != -1;
      
        console.log('isBtn: ', isBtn);
        if (isBtn && tmpText != '') {
          this.moveItemBack();
          return;
        }

        this.fillText(this.sentenceEmptyArr[i], this.curMoveItem.text);

        if (this.curMoveItem.fillRect) {
          this.fillText(this.curMoveItem.fillRect, tmpText);
          this.curMoveItem.text = tmpText;
          this.moveItemBack();
        }
    
        if (isBtn) {
          this.removeBtn(this.curMoveItem);
        }

        this.checkShowSubmit();
        return;
      }
    }

    this.moveItemBack();
    
  }

  removeBtn(btn) {

    this.moveItemBack();
    btn.visible = false;
    // removeItemFromArr(this.btnArr, btn);
    // removeItemFromArr(this.topArr, btn);
  }

  fillText(emptyRect, text) {

    const data = emptyRect.parent.data;

    if (!emptyRect.label) {
      emptyRect.label = this.getFillLabel();
      emptyRect.label.setScaleXY(1);
      emptyRect.label.textAlign = 'center';
      emptyRect.addChild(emptyRect.label);
      
      // this.renderArr.push(emptyRect.label);
    }
    const label = emptyRect.label
    label.text = text;
    // label.width = emptyRect.width / this.mapScale;
    // label.setScaleXY(1);
    label.refreshSize();
    label.anchorY = 0.5;

    // label.y = emptyRect.parent.y //- label.height * label.scaleY ;
    // label.x = emptyRect.parent.x + ( emptyRect.x + emptyRect.width / 2 - label.width / 2 ) * this.mapScale

    label.y = emptyRect.height / 2;
    label.x = ( emptyRect.width / 2  ) 


    // const w1 = emptyRect.width / this.mapScale;
    // const w2 = label.width;
    // label.width = w1// w2 < w1 ? w1: w2;
    

    label['moveOffX'] = -label.width / 2 * label.scaleX;
    label['moveOffY'] = 0// -label.height / 2 * label.scaleY;
    label['baseX'] = label.x;
    label['baseY'] = label.y;
    emptyRect.label = label;
    label.fillRect = emptyRect;
    console.log('label: ', label.width);

  }


  checkShowSubmit() {

    const arr = this.hotZoneArr;



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

     
      if (arr[i].data.gIdx == '0') {
        if (!arr[i].label || !arr[i].label.text || arr[i].label.isDefault) {
          this.hideSubmit();
          return;
        }
      }


   
    }
    
    this.showSubmit();
    
  }



  moveItemBack() {
    if (this.curMoveItem.targetLabel) {
      this.curMoveItem.targetLabel.visible = true;
      removeItemFromArr(this.renderArr, this.curMoveItem);
      return;
    }
    
    this.curMoveItem.x = this.curMoveItem['baseX'];
    this.curMoveItem.y = this.curMoveItem['baseY'];
  }






  templateArr = [];
  initIframe() {

    this.templateArr = this.data.contentObj.templateArr;

    if (this.templateArr.length <= 0) {
      return;
    }
    console.log('arr: ', this.templateArr);

    const c = window['courseware'];
    if (!c) {
      console.error('not found window.courseware')
      return;
    }



    const addPlayUrl = (name, index) => {

      c.getTemplateUrl(name, (data) => {
        console.log('name~: ', name)

        const urlData = JSON.parse(data)
        console.log('data~~:' , data)
        console.log('urlData~~:' , urlData)
        console.log('i~~:' , index)
        this.templateArr[index].playUrl = this.sanitizer.bypassSecurityTrustResourceUrl(urlData.play_url + `?key=${index+1}`);
        this.appRef.tick();
        
        index ++;
        if (index < this.templateArr.length) {
          const {name, last_version, play_url} = this.templateArr[index].template;
          addPlayUrl(name, index);
        }
      })
    }

    const {name, last_version, play_url} = this.templateArr[0].template;
    addPlayUrl(name, 0);

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

    //   const {name, last_version, play_url} = this.templateArr[i].template;

    //   const index = i;
    //   c.getTemplateUrl(name, (data) => {
    //     console.log('name~: ', name)

    //     const urlData = JSON.parse(data)
    //     console.log('data~~:' , data)
    //     console.log('urlData~~:' , urlData)
    //     console.log('i~~:' , index)
    //     this.templateArr[index].playUrl = this.sanitizer.bypassSecurityTrustResourceUrl(urlData.play_url + `?key=${index+1}`);
        
    //   })

      // const playUrl = `https://staging-teach.cdn.ireadabc.com/h5template/${name}/v${last_version}/${play_url}?key=${i+1}`
      // this.templateArr[i].playUrl = this.sanitizer.bypassSecurityTrustResourceUrl(playUrl); 
      // console.log('playUrl: ', playUrl);
    // }
 
    // this.showSubTemplate(0);

    // setTimeout(() => {
    // this.showSubTemplate(1);
      
    // }, 5000);
  }

  showSubTemplate(index) {

    if (this.isTeacher) {
      return;
    }

    console.log('showSubTemplate _ ', index);
    const arr = this.templateArr;
    console.log('arr: ', arr);

    for (let i=0; i<arr.length; i++) {
      arr[i].leftOff = '0vw';
    }
    arr[index].leftOff = '100vw';
    this.appRef.tick();

    if (this.readyObj[(index + 1).toString()]) {
      this.sendCourseIn(index);
    }

  }


  hideSubTemplate(index) {

    this.templateArr[index].isHide = true;
    this.appRef.tick();

  }


  iframeArr;
  readyObj;
  initWindowListener() {


    // const iframeArr = this.iframeArr;

    // // setTimeout(() => {

    //   console.log("iframeContent: ", this.iframeContent);
    //   let divArr = this.iframeContent.nativeElement.children;
    //   console.log('divArr: ', divArr);
    //   for (let i=0; i<divArr.length; i++) {
    //     const iframe = divArr[i].children[0];
    //     console.log('iframe: ', iframe);
    //     iframeArr.push(iframe)
    //   }
  
    //   console.log('iframeArr: ', iframeArr);
    // // }, 1);
   
    this.readyObj = {};

    window.addEventListener('message', (e) => {


      let msgData = e.data;
   

      if (msgData.action === "getData") {


        console.log('msgData.urlParams: ', msgData);
        const key = this.getQueryVariable(msgData.urlParams, 'key');
        if (!key) {
          return;
        }

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


        const index = key - 1;
        const divArr = this.iframeContent.nativeElement.children;
        const iframecont = divArr[index].children[0];

        // const iframecont = iframeArr[key-1]
        const saveData = this.templateArr[index].data;


        console.log("getData e: ", e);

        

        const data = { msg: 'success', data:  JSON.stringify(saveData)};

        iframecont.contentWindow.postMessage({ action: 'getData', data: JSON.stringify(data) }, '*');
        

        
        // const data2 =  { msg: 'success', data:  JSON.stringify({'isShowMore': false})};
        // iframecont.contentWindow.postMessage({ action: 'is_show_more', data: JSON.stringify(data2) }, '*');
        
        // setTimeout(() => {
        //   _this.frameLoaded = true;
        // }, 300);
      }
  
      if (msgData.action === "temp_send_result") {

        console.log(' in temp_send_result');
        console.log('msgData.urlParams: ', msgData);
        let key = msgData.key;
        if (!key) {
          key = '4-3';
        }

        console.log("key: ", key);

        this.serverSendAnswer(key, JSON.parse( msgData.data ));

        const progress = this.getPageData('progress');
        if (progress == '2') {
          this.setPageData('progress', '3');
        } else {
          this.setPageData('progress', '4');
        }
        console.log('in temp_send_result __ msgData: ', msgData);
      }

      if (msgData.action === "temp_show_more") {

        console.log(' in temp_show_more');
        this.checkShowSubTemplateOne();
      }

      
      if (msgData.action == 'course-ready') {
        console.log(' in course-ready msgData: ', msgData)

        console.log('msgData.urlParams: ', msgData);
        const key = this.getQueryVariable(msgData.urlParams, 'key');
        if (!key) {
          return;
        }

        this.readyObj[key] = true;
      }


    });
  }

  sendCourseIn(index) {

    const divArr = this.iframeContent.nativeElement.children;
    const iframecont = divArr[index].children[0];
    

    const data = { msg: 'success', data:  ''};

    iframecont.contentWindow.postMessage({ action: 'airEvents', evt: 'course-in-screen', data: JSON.stringify(data) }, '*');
    
  }

  getQueryVariable(url, variable) {
    var query = url.substring(1);
    var vars = query.split("&");
    for (var i=0;i<vars.length;i++) {
      var pair = vars[i].split("=");
      if(pair[0] == variable){return pair[1];}
    }
    return(false);
  }


  serverResultObj;
  serverSendAnswer(key, data) {
    const c = window['courseware'];
    if (!c) {
      return;
    }

    if (!this.serverResultObj) {
      this.serverResultObj = {};
    }

    this.serverResultObj[key] = data;
    this.serverResultObj.duration = new Date().getTime() - this.localStartTime;
    
    c.sendAnswer(this.serverResultObj);
  }






  isUpdateStop = false;
  update() {

    if (this.isUpdateStop) {
      return;
    }
    this.animationId = window.requestAnimationFrame(this.update.bind(this));
    // 清除画布内容
    this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);

    TWEEN.update();



    this.updateArr(this.renderArr);
    this.updateArr(this.topArr);
    // if (this.curMoveItem) {
    //   this.curMoveItem.update();
    // }
    this.updateItem(this.maskPic);

    // this.updateArr(this.endPageArr);


  }










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

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


  maskBg;
  initHotZone() {


    let curBgRect;
    if (this.bg) {
      curBgRect = this.bg.getBoundingBox();
    }

    let oldBgRect = this.data.contentObj.bgItem.rect;
    if (!oldBgRect) {
      oldBgRect = curBgRect;
    }

    const rate = curBgRect.width / oldBgRect.width;

    this.hotZoneArr = [];
    const arr = this.data.contentObj.hotZoneItemArr;
    if (!arr) return;

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

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

      const data = JSON.parse(JSON.stringify(arr[i]));

      data.rect.x *= rate;
      data.rect.y *= rate;
      data.rect.width *= rate;
      data.rect.height *= rate;

      data.rect.x += curBgRect.x;
      data.rect.y += curBgRect.y;

      const hotZone = this.getHotZoneItem(data, i);

      if (hotZone != null) {
        this.hotZoneArr.push(hotZone);
      }

    }

  }


  openBtn;
  getHotZoneItem(data, index) {

    switch(data.gIdx) {
      case "0": // 轮播图
        return this.setOnePic(data, index);

      case "1": // 选择答题区域
        return this.setOneArea(data);

      case "2": // 简答问题
        return this.setOneShortAnswerPic(data);

      case "3": // 简答题答案区
        return this.setOneShortAnswerRect(data);


      case "4": // 讲解按钮
        return this.setOneBtnVideo(data);

      case "5": // 书写过程按钮
        return this.setOneBtnWrite(data);
 
    }

    return ;
    
  }

  videoBtn;
  setOneBtnVideo(data) {
    console.log('setOneBtnVideo data: ', data)

    const btn = new MySprite();
    btn.init(this.images.get('btn_video'))

    const saveRect = data.rect;

    btn.x = saveRect.x + saveRect.width / 2;
    btn.y = saveRect.y + saveRect.height / 2;
    btn['data'] = data;

    const sx = saveRect.width / btn.width;
    const sy = saveRect.height / btn.height;

    // btn.scaleX = sx;
    // btn.scaleY = sy;
    btn.setScaleXY(this.mapScale);
    btn.visible = false;

    this.renderArr.push(btn);
    this.videoBtn = btn;

    return btn;
  }

  writeBtn;
  setOneBtnWrite(data) {
    console.log('setOneBtnWrite data: ', data)

    const btn = new MySprite();
    btn.init(this.images.get('btn_write'))

    const saveRect = data.rect;

    btn.x = saveRect.x + saveRect.width / 2;
    btn.y = saveRect.y + saveRect.height / 2;
    btn['data'] = data;

    const sx = saveRect.width / btn.width;
    const sy = saveRect.height / btn.height;

    // btn.scaleX = sx;
    // btn.scaleY = sy;
    btn.setScaleXY(this.mapScale);
    btn.visible = false;

    const label = new Label();
    label.text = "书写答题过程"
    btn.addChild(label);
    label.fontColor = '#fff';
    label.textAlign = 'center';
    label.fontSize = 50;

    this.renderArr.push(btn);
    this.writeBtn = btn;
    

    return btn;
  }

  answerQuesPic;
  setOneShortAnswerPic(data) {
    console.log('setOneShortAnswerPic data: ', data)

    const pic = new MySprite();
    pic.init(this.images.get(data.pic_url))

    const saveRect = data.rect;

    pic.x = saveRect.x + saveRect.width / 2;
    pic.y = saveRect.y + saveRect.height / 2;
    pic['data'] = data;

    const sx = saveRect.width / pic.width;
    const sy = saveRect.height / pic.height;

    pic.scaleX = sx;
    pic.scaleY = sy;
    pic.visible = false;
    // this.openBtn = pic;
    this.renderArr.push(pic);
    this.answerQuesPic = pic;

    return pic;
  }

  answerRect;
  answerLabelPic;
  answerRectNode;
  setOneShortAnswerRect(data) {
    console.log('setOneShortAnswerRect data: ', data)

    const saveRect = data.rect;



    const item = new MySprite();
    item.width = saveRect.width;
    item.height = saveRect.height;
    item.x = saveRect.x
    item.y = saveRect.y
    item['data'] = data;
    item.alpha = 0;
    item.visible = false;
    this.answerRectNode = item;


    const answerNormal = this.getMySprite('answer_normal');
    const sx = saveRect.width / answerNormal.width;
    const sy = saveRect.height / answerNormal.height;
    const s = Math.min(sx, sy);
    answerNormal.setScaleXY(s);
    answerNormal.x = answerNormal.width / 2 * answerNormal.scaleX;
    answerNormal.y = answerNormal.height / 2 * answerNormal.scaleY;
    item.addChild(answerNormal);
    item['normalPic'] = answerNormal;
    this.answerRectNode.curRes = 'normalPic';

    const answerRight = this.getMySprite('answer_right');
    answerRight.setScaleXY(s);
    answerRight.x = answerRight.width / 2 * answerRight.scaleX;
    answerRight.y = answerRight.height / 2 * answerRight.scaleY;
    item.addChild(answerRight);
    item['rightPic'] = answerRight;
    answerRight.visible = false;

    const answerWrong = this.getMySprite('answer_wrong');
    answerWrong.setScaleXY(s);
    answerWrong.x = answerWrong.width / 2 * answerWrong.scaleX;
    answerWrong.y = answerWrong.height / 2 * answerWrong.scaleY;
    item.addChild(answerWrong);
    item['wrongPic'] = answerWrong;
    answerWrong.visible = false;

    this.answerRect = answerNormal;


    
    const labelPic = new MySprite();
    item.addChild(labelPic);
    this.answerLabelPic = labelPic;

    // labelPic.load(url).then(img => {

    // });


    
    this.renderArr.push(item);
    return item;
  }


  setOnePic(data, index) {
    console.log('setOnePic data: ', data)
    console.log('setOnePic index: ', index)

    const pic = new MySprite();
    pic.init(this.images.get(data.pic_url))

    const saveRect = data.rect;

    pic.x = saveRect.x + saveRect.width / 2;
    pic.y = saveRect.y + saveRect.height / 2;
    pic['data'] = data;

    const sx = saveRect.width / pic.width;
    const sy = saveRect.height / pic.height;

    pic.scaleX = sx;
    pic.scaleY = sy;
    pic.visible = false;
    // this.openBtn = pic;
    this.renderArr.push(pic);

    return pic;
  }


  optionItemArr;
  curAreaItem;
  setOneArea(data) {

    console.log('setOneBtn data: ', data)

    const saveRect = data.rect;
    // const item = new ShapeRect(this.ctx);
    // item.setSize(saveRect.width, saveRect.height);
    // item.fillColor = '#ff0000';

    const item = new MySprite();
    item.width = saveRect.width;
    item.height = saveRect.height;
    item.x = saveRect.x
    item.y = saveRect.y
    item['data'] = data;
    item.alpha = 0;
    item.visible = false;


    const w = item.width;
    const h = item.height;
    const subH = h / 6;

    const ques = this.getMySprite(this.data.contentObj.ques_pic_url);
    const sx = w / ques.width;
    const sy = subH * 1.5 / ques.height;
    ques.setScaleXY(Math.min(sx, sy));
    ques.x = w / 2;
    ques.y = subH;
    item.addChild(ques);
    
    this.optionItemArr = [];

    const optionArr = this.data.contentObj.optionArr;
    const baseY = subH * 2.5;
    for (let i=0; i<4; i++) {

      if (optionArr[i]) {
        const opItem = this.getOneOpItem(optionArr[i]);
        const sx = w / opItem.width; 
        const sy = subH / opItem.height;
        opItem.setScaleXY(Math.min(sx, sy));
        opItem.y = baseY + i * subH;
        opItem.x = w / 2;
        item.addChild(opItem);

        this.optionItemArr.push(opItem);
      }
     
    }


    this.curAreaItem = item;
    this.renderArr.push(item);
    return item;
  }


  resetAnswerQues(data) {
    const quesPic = this.answerQuesPic;
    const rect = quesPic.getBoundingBox();

    quesPic.load(data.ques_pic_url).then(img => {

      const sy = rect.height / quesPic.height;
      quesPic.setScaleXY(sy);
      quesPic.x = rect.x + quesPic.width / 2 * quesPic.scaleX;
    })

    this.renderArr.push(quesPic);
  }

  resetAnswerArea() {

    const data = this.answerRectNode.data;

    const saveRect = data.rect;

    const item = new MySprite();
    item.width = saveRect.width;
    item.height = saveRect.height;
    item.x = saveRect.x
    item.y = saveRect.y
    item['data'] = data;
    // item.alpha = 0;
    // item.visible = false;
    this.answerRectNode = item;


    const answerNormal = this.getMySprite('answer_normal');
    const sx = saveRect.width / answerNormal.width;
    const sy = saveRect.height / answerNormal.height;
    const s = Math.min(sx, sy);
    answerNormal.setScaleXY(s);
    answerNormal.x = answerNormal.width / 2 * answerNormal.scaleX;
    answerNormal.y = answerNormal.height / 2 * answerNormal.scaleY;
    item.addChild(answerNormal);
    item['normalPic'] = answerNormal;
    this.answerRectNode.curRes = 'normalPic';

    const answerRight = this.getMySprite('answer_right');
    answerRight.setScaleXY(s);
    answerRight.x = answerRight.width / 2 * answerRight.scaleX;
    answerRight.y = answerRight.height / 2 * answerRight.scaleY;
    item.addChild(answerRight);
    item['rightPic'] = answerRight;
    answerRight.visible = false;

    const answerWrong = this.getMySprite('answer_wrong');
    answerWrong.setScaleXY(s);
    answerWrong.x = answerWrong.width / 2 * answerWrong.scaleX;
    answerWrong.y = answerWrong.height / 2 * answerWrong.scaleY;
    item.addChild(answerWrong);
    item['wrongPic'] = answerWrong;
    answerWrong.visible = false;

    this.answerRect = answerNormal;


    const labelPic = new MySprite();
    item.addChild(labelPic);
    this.answerLabelPic = labelPic;

    
    this.renderArr.push(item);
  }

  changeAnswerArea() {

    const data = this.data.contentObj.answer_obj;
    this.showSmallTitle(data);

    this.resetAnswerQues(data)
    
    this.resetAnswerArea()

  }


  changeChoiceArea(data) {
    console.log('changeChoiceArea data: ', data)
    this.cleanSmallTitle();

    this.showSmallTitle(data);

    if (this.curAreaItem) {
      data.rect = this.curAreaItem.data.rect;
    }

    
    const saveRect = data.rect;
    // const item = new ShapeRect(this.ctx);
    // item.setSize(saveRect.width, saveRect.height);
    // item.fillColor = '#ff0000';

    const item = new MySprite();
    item.width = saveRect.width;
    item.height = saveRect.height;
    item.x = saveRect.x
    item.y = saveRect.y
    item['data'] = data;
    // item.alpha = 0;
    // item.visible = false;


    const w = item.width;
    const h = item.height;
    const subH = h / 6;

    const ques = this.getMySprite(data.ques_pic_url);
    const sx = w / ques.width;
    const sy = subH * 1.5 / ques.height;
    ques.setScaleXY(Math.min(sx, sy));
    ques.x = w / 2;
    ques.y = subH;
    item.addChild(ques);
    
    this.optionItemArr = [];

    const optionArr = data.optionArr;

    console.log('~optionArr: ', optionArr);

    const baseY = subH * 2.5;
    for (let i=0; i<optionArr.length; i++) {

      if (optionArr[i]) {
        const opItem = this.getOneOpItem(optionArr[i]);
        const sx = w / opItem.width; 
        const sy = subH / opItem.height;
        opItem.setScaleXY(Math.min(sx, sy));
        opItem.y = baseY + i * subH;
        opItem.x = w / 2;
        item.addChild(opItem);

        this.optionItemArr.push(opItem);
      }
     
    }


    this.curAreaItem = item;
    this.renderArr.push(item);
    return item;
  }

  getOneOpItem(data) {

  
    const opItem = this.getMySprite('op_item');
    const opItemNode = this.getMySprite('op_item');
    opItemNode.alpha = 0;
    opItemNode.childDepandAlpha = false;

    opItemNode.width = opItem.width;
    opItemNode.height = opItem.height;
    opItemNode.addChild(opItem);
    opItemNode['defaultPic'] = opItem;
    opItemNode['curRes'] = 'defaultPic';

    const opItemWrong = this.getMySprite('op_item_wrong');
    opItemNode.addChild(opItemWrong);
    opItemWrong.visible = false;
    opItemNode['wrongPic'] = opItemWrong;
    const wrongIcon = this.getMySprite('icon_wrong');
    wrongIcon.x = opItemWrong.width / 2;
    opItemWrong.addChild(wrongIcon)


    const opItemRight = this.getMySprite('op_item_right');
    opItemNode.addChild(opItemRight);
    opItemRight.visible = false;
    opItemNode['rightPic'] = opItemRight;
    const rightIcon = this.getMySprite('icon_right');
    rightIcon.x = opItemRight.width / 2;
    opItemRight.addChild(rightIcon)

    const opItemNormal = this.getMySprite('op_item_normal');
    opItemNode.addChild(opItemNormal);
    opItemNormal.visible = false;
    opItemNode['normalPic'] = opItemNormal;

    const label = new Label();
    label.text = data.id;
    label.fontColor = '#ffffff';
    label.x = -opItemNode.width / 2 + 50;
    opItemNode.addChild(label);


    const subX = 150;
    const opPic = this.getMySprite(data.pic_url);
    const sx = (opItemNode.width - subX) / opPic.width;
    const sy = (opItemNode.height - 20) / opPic.height;
    opPic.setScaleXY(Math.min(sx, sy));
    opPic.anchorX = 0;
    opPic.x = - opItemNode.width / 2 + subX;
    opItemNode.addChild(opPic);

    console.log('op data: ', data);

    opItemNode['data'] = data;
    return opItemNode;
  }

  

  setOneRect(data, index) {

    const saveRect = data.rect;
    const item = new ShapeRectNew(this.ctx);
    item.setSize(saveRect.width, saveRect.height, 5);
    item.setOutLine('#dcc077', 2);
    item.fill = false;
    item.x = saveRect.x
    item.y = saveRect.y
    // item.setScaleXY(this.bg.scaleX);
    item.fillColor = '#dcc077';
    item['data'] = data;
    // item.alpha = 0;
    this.scrollView.addItem(item);


    const rectLabel = this.getFillLabel();
    rectLabel.topH = 8;
    rectLabel.fontSize = this.inputFontSize;
    rectLabel.disH = 0;
    rectLabel.offW = 0;
    rectLabel.textBaseline = 'top'
    rectLabel.width = item.width;
    rectLabel.fontSize *= (this.bg.scaleX);
    // targetRect.label.x = ( targetRect.width / 2  ) 
    item['label'] = rectLabel;
    item.addChild(item['label']);

    this.addLabelMask(item, rectLabel);

    rectLabel.text = 'Please Enter ...';
    rectLabel.fontColor = '#cccccc'
    rectLabel['isDefault'] = true;



    // const subX = data.rect.x - this.bg.data.rect.x;
    // const subY = data.rect.y - this.bg.data.rect.y;

    // item.x = subX * this.mapScale //- this.bg.width / 2;
    // item.y = subY * this.mapScale //- this.bg.height / 2;
    // // item.y -= this.bg.height / 2;
    // this.bg.addChild(item);


    const circle = new ShapeCircle();
    circle.setRadius(20 * this.bg.scaleX);
    circle.x = item.x + item.width;
    circle.y = item.y;
    circle.fillColor = '#dcc077'
    this.scrollView.addItem(circle);

    const label = new Label();
    label.text = index + 1;
    label.fontColor = '#ffffff';
    label.textAlign = 'center';
    label.fontSize = 28 
    label.fontName = 'Aileron-Bold';
    label.y = 2;
    circle.addChild(label);

    // 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.canvasScale  - this.canvasLeft;
      this.my = event.touches[0].pageY * this.canvasScale - this.canvasTop;
    };

    const setMxMyByMouse = (event) => {
      this.mx = event.offsetX * this.canvasScale;
      this.my = event.offsetY * this.canvasScale;
    };
    // ---------------------------------------------


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

    // element.addEventListener('mousewheel', (event) => {
    //   setMxMyByMouse(event);
    //   if (event.deltaY > 0) {
    //     this.wheelDown(event);
    //   } else {
    //     this.wheelUp(event);
    //   }
    // });
  }



  wheelUp(event: any) {
    if (this.resultSv) {
      if (this.checkClickTarget(this.resultSv)) {
        this.resultSv.onWheelUp(event.deltaY);
      }
    } else {
      if (this.checkClickTarget(this.scrollView)) {
        this.scrollView.onWheelUp(event.deltaY);
      }
    }
 
  }


  wheelDown(event: any) {
    if (this.resultSv) {
      if (this.checkClickTarget(this.resultSv)) {
        this.resultSv.onWheelDown(event.deltaY);
      }
    } else {
      if (this.checkClickTarget(this.scrollView)) {
        this.scrollView.onWheelDown(event.deltaY);
      }
    }

  }

  playAudio(key, now = false, callback = null) {

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

      const audioNew = new Audio();
      audioNew.src = audio.src;
      audioNew.load();
      // audioNew.play();

      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 => {
          // img['setAttribute']("crossOrigin",'Anonymous')

          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.crossOrigin = "anonymous";
      img.onload = () => resolve(img);
      img.onerror = reject;
      img.src = url;
    });
  }

  preloadAudio(url) {
    return new Promise((resolve, reject) => {
      const audio = new Audio();
      resolve({})
      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();
  }

  checkClickTargetSv(target) {

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

    const scale = 1 // this.mapScale;

    let tmpRect = target.getBoundingBox();

    const svBox = this.scrollView.getBoundingBox();

   
    const x = svBox.x +  tmpRect.x * scale;
    const y = svBox.y + tmpRect.y * scale;
    const width = tmpRect.width * scale;
    const height = tmpRect.height * scale;
    const rect = {x, y, width, height};
    
    
    // const contentBox = this.scrollView.content.getBoundingBox();

    // rect.x += contentBox.x + svBox.x;
    // rect.y += contentBox.y + svBox.y;

    // console.log('rect: ', rect);
    // console.log('this.mx: ', this.mx);
    // console.log('this.my: ', this.my);

    // const shape = new ShapeRectNew();
    // shape.x = rect.x;
    // shape.y = rect.y;
    // shape.fillColor = '#0000ff'
    // shape.alpha = 0.5;
    // shape.setSize(rect.width, rect.height, 1);
    // this.renderArr.push(shape);


    if (this.checkPointInRect(this.mx, this.my, rect)) {
      return true;
    }
    return false;
  }

  checkClickTarget(target) {

    const rect = target.getBoundingBox();

    // rect.x /= 2;
    // rect.y /= 2;
    // rect.width /= 2;
    // rect.height /= 2;


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

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

  b64ToUint8Array(b64Image) {

    var img = atob(b64Image.split(',')[1]);
    var img_buffer = [];
    var i = 0;
    
    while (i < img.length) {
      img_buffer.push(img.charCodeAt(i));
      i++;
    }
    
    return new Uint8Array(img_buffer);
  }

  convertCanvasToImage() {

    console.log('1');

    if (!this.uploadUrl) {
      // this.userResultPic = ''//true
      this.sendResult();
      return
    }
    console.log('2 uploadUrl: ', this.uploadUrl.toString());

    const src = this.canvas.nativeElement.toDataURL("image/png");

    const arr = src.split(','),
    mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]);
    let n = bstr.length;
    const u8arr = new Uint8Array(n);
    while ( n -- ) {
      u8arr[n] = bstr.charCodeAt(n);
    }
    const obj = new Blob([u8arr], {type: mime});
    const fd = new FormData();
    fd.append("file", obj, "cw_cover.png");

    // 上传截图
    this.http.post(this.uploadUrl, fd).subscribe((res) => {
      // 存储服务器的截图url
      if (res['url']) {
        console.log('res url: ', res['url']);
        this.userResultPic = res['url'];
        this.sendResult();
      }
    });


  }

  httpServer(type, url, options, cb) {

    this.http[type](url, options)
      .subscribe( val =>  {

        console.log("Post call successful value returned in body", val);

        cb(val);
      
      }, error => {
        console.log("Post call in error", error);
        cb(error);

      }, () => {
        console.log("The Post observable is now completed.");
        cb(null);

      }
    );

  }

}
