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

import {
  MySprite,
  Label,
  moveItem,
  rotateItem,
  removeItemFromArr,
  ShapeRect,
  RichText,

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

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

import * as _ from 'lodash';
import TWEEN from '@tweenjs/tween.js';
import { THIS_EXPR } from '@angular/compiler/src/output/output_ast';


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

  animationId: any;
 
  renderArr;

  number_id = 1;

  index_item = 0;

  canvasLeft;
  canvasTop;

  optionRect;

  mx;
  my;

  init_bool = true;

  values_bool = [0,0,0,0];

  //按钮
  img_button = [];
  label_title;
  items_Text = [[],[],[],[]];
  item = [];
  answer = [[],[],[],[]];
  play_button;
  label_title_top_bg;

  audio_bool = false;

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

  canvasBaseW = 1280;
  canvasBaseH = 720;

  bgWidth = 1280;
  bgHeight = 720;

  ctx; 

  play_button_bool = false;
  currentTime = 0;
  
  KEY = 'hw-24';

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

  winResizeEventStream = new Subject();

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

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

  initListener() {
    this.renderAfterResize();

    this.winResizeEventStream
      .pipe(debounceTime(500))
      .subscribe(data => {
        this.renderAfterResize();
      });


    // ---------------------------------------------
    const setParentOffset = () => {
      const rect = this.canvas.nativeElement.getBoundingClientRect();
      this.canvasLeft = rect.left;
      this.canvasTop = rect.top;
    };
    const setMxMyByTouch = (event) => {
      if (event.touches.length <= 0) {
        return;
      }
      if (this.canvasLeft == null) {
        setParentOffset();
      }
      this.mx = event.touches[0].pageX - this.canvasLeft;
      this.my = event.touches[0].pageY - this.canvasTop;
    };

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


    let firstTouch = true;

    const touchDownFunc = (e) => {
      if (firstTouch) {
        firstTouch = false;
        removeMouseListener();
      }
      console.log('touch down');
      setMxMyByTouch(e);
      this.mapDown(e);
    };
    const touchMoveFunc = (e) => {
      setMxMyByTouch(e);
      this.mapMove(e);
    };
    const touchUpFunc = (e) => {
      setMxMyByTouch(e);
      this.mapUp(e);
    };

    const mouseDownFunc = (e) => {
      if (firstTouch) {
        firstTouch = false;
        removeTouchListener();
      }
      console.log('mouse down');
      setMxMyByMouse(e);
      this.mapDown(e);
    };
    const mouseMoveFunc = (e) => {
      setMxMyByMouse(e);
      this.mapMove(e);
    };
    const mouseUpFunc = (e) => {
      setMxMyByMouse(e);
      this.mapUp(e);
    };


    const element = this.canvas.nativeElement;

    const addTouchListener = () => {
      element.addEventListener('touchstart', touchDownFunc);
      element.addEventListener('touchmove', touchMoveFunc);
      element.addEventListener('touchend', touchUpFunc);
      element.addEventListener('touchcancel', touchUpFunc);
    };
    const removeTouchListener = () => {
      element.removeEventListener('touchstart', touchDownFunc);
      element.removeEventListener('touchmove', touchMoveFunc);
      element.removeEventListener('touchend', touchUpFunc);
      element.removeEventListener('touchcancel', touchUpFunc);
    };

    const addMouseListener = () => {
      element.addEventListener('mousedown', mouseDownFunc);
      element.addEventListener('mousemove', mouseMoveFunc);
      element.addEventListener('mouseup', mouseUpFunc);
    };
    const removeMouseListener = () => {
      element.removeEventListener('mousedown', mouseDownFunc);
      element.removeEventListener('mousemove', mouseMoveFunc);
      element.removeEventListener('mouseup', mouseUpFunc);
    };

    addMouseListener();
    addTouchListener();
  }

  checkClickTarget(target) {

    const rect = target.getBoundingBox();

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

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

    if(!this.data.contentObj.audio_url){
      this.data.contentObj.audio_url= "";
    }

    if(!this.data.contentObj.title){
      this.data.contentObj.title = {
        text:"",
        audio_url:"",
        number: "",
      };
      
    }

    if(!this.data.contentObj.values){
      this.data.contentObj.values = [];
    }

    if(this.data.contentObj.values.length == 0 && this.data.contentObj.title.text == "" && this.data.contentObj.title.audio_url == "" && this.data.contentObj.audio_url == "" && this.data.contentObj.title.number == ""){
      const value_Arr = [];
      const text_1 = "I think the";
      const text_2 = "could chew the"

      for(let i = 0;i < 4;i++){
        if(i % 2 == 0){
          value_Arr.push({
            text : text_1,
            number : "true",
            img_url : "assets/play/default/1.png",
            audio_url : "assets/play/default/item1.mp3",
            answer : "3",
            answer_color: "B8C955",
            word : ["I","think","the","chimp"]
          })
        }
        else{
          value_Arr.push({
            text : text_2,
            number : "false",
            img_url : "assets/play/default/2.png",
            audio_url : "assets/play/default/item2.mp3",
            answer : "3",
            answer_color: "613821",
            word : ["could","chew","the","chick"]
          })
        }
      }

      this.data.contentObj.title.text = 'Listen,trace and write.Then chant.';
      this.data.contentObj.title.audio_url = 'assets/play/default/audio.mp3';
      this.data.contentObj.audio_url = 'assets/play/music/demo.mp3';
      this.data.contentObj.title.number = "c";

      this.data.contentObj.values = value_Arr;
    }

    // if (!this.data.contentObj.title && !this.data.contentObj.audio_url) {
    //   this.data.contentObj.title.text = 'Listen,trace and write.Then chant.';
    //   this.data.contentObj.title.audio_url = 'assets/play/default/audio.mp3';
    //   this.data.contentObj.audio_url = 'assets/play/music/demo.mp3';
    //   console.log(123123);
      
    // }

    // if(this.data.contentObj.title.text == "" && this.data.contentObj.values.length == 0){
    //   this.data.contentObj.title.text = 'Listen,trace and write.Then chant.';
    //   console.log(123);
      
    // }
  }

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

  update() {

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

    this.updateArr(this.renderArr);

  }
  //加载数据
  load_date(){
    const contentObj = this.data.contentObj;
    if (contentObj) {


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

      for(let i = 0; i < contentObj.values.length;i++){
        addPicUrl(contentObj.values[i].img_url);
      }
    }

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

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

      this.init();
      this.update();
    });
  }

  loadResources() {
    const pr = [];
    this.rawImages.forEach((value, key) => {// 预加载图片

      const p = this.preload(value)
        .then(img => {
          this.images.set(key, img);
        })
        .catch(err => console.log(err));

      pr.push(p);
    });

    this.rawAudios.forEach((value, key) => {// 预加载图片

      const a = this.preloadAudio(value)
        .then(() => {
          // this.images.set(key, img);
        })
        .catch(err => console.log(err));

      pr.push(a);
    });
    return Promise.all(pr);
  }
  //加载图片
  preload(url) {
    return new Promise((resolve, reject) => {
      const img = new Image();
      img.onload = () => resolve(img);
      img.onerror = reject;
      img.src = url;
    });
  }
  //加载声音
  preloadAudio(url) {
    return new Promise((resolve, reject) => {
      const audio = new Audio();
      audio.oncanplay = (a) => {
        resolve();
      };
      audio.onerror = () => {
        reject();
      };
      audio.src = url;
      audio.load();
    });
  }

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


  ngOnInit() {


    const getData = (<any> window).courseware.getData;
    getData((data) => {
      if (data && typeof data == 'object') {
        this.data = data;
      } else {
        this.data = {msg: "xxxx"};
      } 

      this.initDefaultData();

      this.load_date();
      this.initAudio();
      this.initListener();

      // this.initView();
      
    }, this.KEY);
 
  }

  initData(){
    this.renderArr = [];
  }

  initAudio() {

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

    const addUrlToAudioObj = (audioUrl) => {

      if (audioUrl) {

        const audio = new Audio();
        audio.src = audioUrl;
        audio.load();
        this.audioObj[audioUrl] = audio;
      }
    };


    let arr = contentObj.values;
    

    if (arr) {
      for (let i = 0; i < arr.length; i++) {
        addUrlToAudioObj(arr[i].audio_url);
      }
    }
    addUrlToAudioObj(this.data.contentObj.audio_url);
    addUrlToAudioObj(this.data.contentObj.title.audio_url);
    addUrlToAudioObj("assets/play/music/click.mp3");
    


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

  }
 
  ngOnDestroy() {
     
  }

  playAudio_init(){
    for(let i = 0; i < this.data.contentObj.values.length;i++){
      if(this.data.contentObj.values[i].audio_url){
        let audio = this.audioObj[this.data.contentObj.values[i].audio_url];
        audio.pause();
        audio.currentTime = 0;
      }
    }
    if(this.data.contentObj.title.audio_url)
    {
      let audio = this.audioObj[this.data.contentObj.title.audio_url];
      audio.pause();
      audio.currentTime = 0;
    }
  }

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

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

  playAudio_ps(bool,key){
    const audio = this.audioObj[key];

    if(!bool){
      audio.currentTime = this.currentTime;
      this.play_button.init(this.images.get('stop'));
      audio.play();
      this.play_button_bool = !bool;
      
    }
    else{
      audio.pause();
      this.play_button.init(this.images.get('play'));
      this.currentTime = audio.currentTime;
      this.play_button_bool = !bool;
    }
  }

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

    this.canvas.nativeElement.width = this.wrap.nativeElement.clientWidth;
    this.canvas.nativeElement.height = this.wrap.nativeElement.clientHeight; 
 
    this.initData();
    this.initCtx();
    this.initView();


    window["air"].hideAirClassLoading("hw_024",this.data);
  
  }  

  initCtx() {

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

    this.ctx.font="64px MMTextBook-Bold";

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

  addBlanks(item,text_value,as_v){
    const Blanks = new Label();
    Blanks.text = "";
    for(let x = 0; x < text_value.length;x++)
    {
      Blanks.text += "_";
    }
    Blanks.fontSize = item.fontSize;
    Blanks.width = this.ctx.measureText(Blanks.text).width;
    Blanks.height = 60;
    Blanks.textAlign = 'center';
    Blanks.fontColor = "#000000";
    Blanks.fontSize = 64;
    
    Blanks.x = this.ctx.measureText(item.text).width;
    Blanks.y = item.y + 5; 
    this.items_Text[this.index_item][as_v] = Blanks;
    
    item.addChild(Blanks);
  }

  addAnswer(item,as,index,bool){
    const Answer = new Label();
    if(bool[index]){
      Answer.text = this.data.contentObj.values[index].word[this.data.contentObj.values[index].answer[as]];
    }
    else
    Answer.text = "";
    Answer.fontColor = "#" + this.data.contentObj.values[index].answer_color;
    Answer.textAlign = 'center';
    Answer.fontName = "MMTextBook-Bold"
    Answer.fontSize = item.fontSize;
    Answer.width = this.ctx.measureText(Answer.text).width;
    Answer.x = this.ctx.measureText(item.text).width;
    this.answer[index][as] = Answer;
    item.addChild(Answer);
  }

  //Answer.text = this.data.contentObj.values[index].answer;
  addNumber(item,Arr,nu){
    const Number = new Label();
    Number.fontName = "MMTextBook-Bold";
    
    
    if(Arr[nu].number == "true"){
      Number.text = this.number_id + ". ";
      Number.fontSize = item.fontSize;
      Number.color = "#000000";
      this.number_id+=1;
      
    }
    else{
      Number.text = "   ";
      Number.fontSize = item.fontSize;
      Number.color = "#000000";
    }
    
    Number.x = -70;
    // Number.y = 5;
    item.addChild(Number);
  }

  initView(){

    let Bgx = document.body.clientWidth /this.bgWidth;
    let Bgy = document.body.clientHeight /this.bgHeight;
    // let Bgy = document.body.clientWidth /this.bgHeight;

    const bg_img = new MySprite();
    bg_img.init(this.images.get('bg'));
    bg_img.width = 0;
    bg_img.height = 200;
    bg_img.setScaleXY(1);
    const sx = this.canvasWidth / this.canvasBaseW;

    // const bgRect = new ShapeRect();
    // bgRect.setSize(57, 65);
    // bgRect.fillColor = '#f8c224';
    // bgRect.setScaleXY(sx);
    // bgRect.x = 65 * sx;
    // this.renderArr.push(bgRect);

    const play_button = new MySprite();
    if(this.play_button_bool)
    play_button.init(this.images.get('stop'));
    else
    play_button.init(this.images.get('play'));
    play_button.setScaleXY(Math.max(Math.min(Bgx ,Bgy) * 0.8,0.2));
    
    play_button.x = document.body.clientWidth - (50 * document.body.clientWidth / 1600);
    this.play_button = play_button;
    play_button.y = document.body.clientHeight - (40 * document.body.clientHeight / 805);
    if(this.play_button_bool,this.data.contentObj.audio_url)
    bg_img.addChild(play_button);

    this.renderArr.push(bg_img);

    const label_title_top_bg = new MySprite();
    label_title_top_bg.init(this.images.get('title_bg'));
    label_title_top_bg.setScaleXY(Bgx * 0.5);
    label_title_top_bg.x = 65 * sx + 35 * (document.body.clientWidth / 1600);
    label_title_top_bg.y = Bgx * 32;

    const label_title_top = new Label();
    label_title_top.text = this.data.contentObj.title.number.toUpperCase();
    label_title_top.fontName = 'BRLNSDB';
    label_title_top.setScaleXY(1);
    label_title_top.fontSize = 110;
    label_title_top.y = 0;
    
    label_title_top.fontColor = '#FFDB84';
    label_title_top.textAlign = 'center';
    label_title_top_bg.addChild(label_title_top);

    const label_title = new Label();
    label_title.text = this.data.contentObj.title.text;
    label_title.fontName = 'FUTURAB';
    label_title.setMaxSize(1000);
    label_title.fontSize = Math.min(Bgx * 45,55);
    label_title.width = this.ctx.measureText(label_title.text).width * 0.95;
    // label_title.x = label_title_top_bg.x - 800 + label_title_top_bg.width / 2 * Bgx + this.ctx.measureText(label_title.text).width * Bgx;
    label_title.x = label_title_top_bg.x + label_title_top_bg.width / 2 * Bgx + this.ctx.measureText(label_title.text).width * label_title.fontSize / 64 / 1.9;
    label_title.y = label_title_top_bg.y + 5 * Bgx;
    
  
    label_title.fontColor = '#000';
    label_title.fontWeight = 300;
    label_title.textAlign = 'center';

    bg_img.addChild(label_title_top_bg);

    this.label_title_top_bg = label_title_top_bg;
    

    this.label_title = label_title;
    
    bg_img.addChild(label_title);

    const optionRect = new ShapeRect();
    optionRect.init();
    optionRect.fillColor = '#ffffff';
    optionRect.x = this.wrap.nativeElement.clientWidth / 2;
    optionRect.y = this.wrap.nativeElement.clientHeight * 0.5;
    
    optionRect.width = this.wrap.nativeElement.clientWidth;
    optionRect.height = this.wrap.nativeElement.clientHeight * 0.75;
    optionRect.setShadow(0, 4, 10);
    this.renderArr.push(optionRect);
    this.optionRect = optionRect;

    let Arr = this.data.contentObj.values;

    this.number_id = 1;
    this.index_item = 0;
    let c = true;

    for(let i = 0; i < Arr.length;i++){
      let as_v = 0;
      const items = new Label();
      items.fontName = 'MMTextBook-Bold';
      items.fontSize = 64;
      items.text = "";
      items.fontWeight = 300;
      c = true;
      for(let j = 0; j < Arr[i].word.length; j++){
          if(j != Arr[i].answer[as_v])
          items.text += Arr[i].word[j] + " ";
         else{
           for(let x = 0; x < Arr[i].word[j].length;x++)
           {
             
             if(x == Math.floor(Arr[i].word[j].length / 2 ))
             {
               items.text += " ";
               this.addBlanks(items,Arr[i].word[Arr[i].answer[as_v]],as_v);
               this.addAnswer(items,as_v,i,this.values_bool);
               as_v++;
             }
             items.text += " ";
           }
           items.text += " ";
         }
      }
      
      
      items.text += ".";
      items.y = Bgy * 100 * i - Bgy * 160;
      items.x = -Bgx * 450;
      items.width = items.text.length * 30;
      items.setScaleXY(Math.min(Bgx,Bgy));
      if(this.values_bool[i])
      items.fontColor = "#000000";
      else
      items.fontColor = "#DEE0DF";

      this.item[i] = items;
      
      this.addNumber(items,Arr,i);


      const img = new MySprite();
      
      img.init(this.images.get(Arr[i].img_url));
      img.setScaleXY(Math.min(300 / img.width,140 / img.height) * Math.min(Math.max(Bgx,Bgy) * 0.6,0.7));
      img.x = this.ctx.measureText(items.text).width + 100;
      
      this.img_button[i] = img;
      
      items.addChild(img);

      optionRect.addChild(items);

      this.index_item++;

    }

  }

  onclick_img(index){
    this.playAudio(this.data.contentObj.values[index].audio_url, true);
    return;
  }

  onclick_items_text(item,index){
    item.fontColor = "#000000";

    for(let i = 0; i < this.items_Text[index].length;i++){
      
      this.answer[index][i].text = this.data.contentObj.values[index].word[this.data.contentObj.values[index].answer[i]];
    }
  }

  mapDown(event) {

    if(this.checkClickTarget(this.label_title) || this.checkClickTarget(this.label_title_top_bg)){
      this.playAudio(this.data.contentObj.title.audio_url, true);
      return;
    }

    if(this.checkClickTarget(this.play_button)){
      this.playAudio_ps(this.play_button_bool,this.data.contentObj.audio_url);
    }
    if(this.data.contentObj.audio_url)
    {
      let _this = this;
      this.audioObj[this.data.contentObj.audio_url].addEventListener('ended', function () { 
        _this.play_button.init(_this.images.get('play'));

        _this.play_button_bool = false;
        _this.currentTime = 0;
        }, false);
      
    }


    
    for(let i = 0; i < this.data.contentObj.values.length; i++){
      if(this.checkClickTarget(this.img_button[i])){
        
        this.onclick_img(i);
        
        return;
      }
    }
    
    
    for(let i = 0; i < this.data.contentObj.values.length; i++){
      for(let j = 0;j < this.items_Text[i].length;j++){
        if(this.checkClickTarget(this.items_Text[i][j])){
          this.onclick_items_text(this.item[i],i);
          this.values_bool[i] = 1;
          
          // this.onclick_items_text(this.items_Text);
          
          return;
        }
      }
    }
  }

  mapMove(event){

  }
  mapUp(event){

  }
  

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