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

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

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

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




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

  @ViewChild('canvas') canvas: ElementRef;
  @ViewChild('wrap') wrap: ElementRef;

  // 数据
  data;

  ctx;

  canvasWidth = 1280; // canvas实际宽度
  canvasHeight = 720; // canvas实际高度

  canvasBaseW = 1280; // canvas 资源预设宽度
  canvasBaseH = 720;  // canvas 资源预设高度

  mx; // 点击x坐标
  my; // 点击y坐标


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

  images = new Map();

  animationId: any;
  winResizeEventStream = new Subject();

  audioObj = {};

  renderArr;
  mapScale = 1;

  canvasLeft;
  canvasTop;

  saveKey = 'test_0011';


  top_bg;

  canTouch = true;

  mousemove_cur;

  mousedown_cur;

  //课程信息
  lesson;

  //课程背景图片
  lesson_bg;

  //字母（组合）显示背景图片
  title_bg;

  title_arr = [];

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

  //单词高度
  word_height = 0;

  //最大宽度
  max_word_width = 100;

  //间隔宽度
  interval_width = 200;

  //间隔高度
  interval_height = 150;

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

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

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

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

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

    for(let tKey in letters){
      if(!letters[tKey].loaded){
        flag = true;
        break;
      }
    }
    
    if(!flag){
      this.wordLoad[id].loaded = true;
    }
    else{
      this.wordLoad[id].loaded = false;
    }
    
    console.log('wordLoad', this.wordLoad);
  }

  getWordLoaded(id: string):boolean{

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

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

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

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

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

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

  getLetterSpriteFromWordLoaded(id: string){

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

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

    return letters;
  }

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


  ngOnInit() {

    this.data = {};

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

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

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

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

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

      //加载完成播放音乐
      this.playAudio("newpage");
      
    }, this.saveKey);
  }

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


  load() {

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


  init() {

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






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

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







  initListener() {

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


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

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

      
    };
    // ---------------------------------------------


    let firstTouch = true;

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

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


    const element = this.canvas.nativeElement;

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

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

    addMouseListener();
    addTouchListener();
  }


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

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



  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) => {// 预加载音频

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

        pr.push(a);
      }
      
    });
    return Promise.all(pr);
  }

  preload(url) {
    return new Promise((resolve, reject) => {
      const img = new Image();
      // img.crossOrigin = "anonymous";
      img.onload = () => resolve(img);
      img.onerror = reject;
      img.src = url;
    });
  }

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


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





  checkClickTarget(target) {

    const rect = target.getBoundingBox();
    console.log('rect', rect);
    if (this.checkPointInRect(this.mx, this.my, rect)) {console.log('check', true);
      return true;
    }
    return false;
  }

  checkPointInRect(x, y, rect) {
    if (x >= rect.x && x <= rect.x + rect.width) {
      if (y >= rect.y && y <= rect.y + rect.height) {
        return true;
      }
    }
    return false;
  }





  addUrlToAudioObj(key, url = null, vlomue = 1, loop = false, callback = null) {

    const audioObj = this.audioObj;
  
    if (url == null) {
      url = key;
    }
    console.log('add audio', key);
    this.rawAudios.set(key, url);

    const audio = new Audio();
    audio.src = url;
    audio.load();
    audio.loop = loop;
    audio.volume = vlomue;

    audioObj[key] = audio;

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

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






  // ======================================================编写区域==========================================================================





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

    if (!this.data.pic_url) {
      this.data.pic_url = 'assets/play/default/pic.jpg';
    }
  }


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

    
  }

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

    // 音效
    this.addUrlToAudioObj('click', this.rawAudios.get('click'), 0.3);

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

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

    //初始化tilte字组（组合）音效
    for(let i = 0; i < this.data.titleArr.length; ++ i){
      let title = this.data.titleArr[i];
      
      if(title.title_audio_url && title.title_audio_url != ""){
        this.addUrlToAudioObj(title.title_audio_url);
      }
    }

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

      for(let j = 0; j < word.letters.length; ++ j){
        let letter = word.letters[j];

        if(letter.letter_audio_url && letter.letter_audio_url != ""){
          this.addUrlToAudioObj(letter.letter_audio_url);
        }
      }
    }

    
  }



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

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

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



  }



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


    this.initPic();

  }

  initPic() {

    const pic1 = new MySprite();
    pic1.init(this.images.get('top_bg'));
    pic1.x = this.canvasWidth / 2;
    pic1.y = pic1.height/2;
    pic1.scaleX = this.canvasWidth/pic1.width;
    pic1.update();

    this.renderArr.push(pic1);
    this.top_bg = pic1;

    const lesson_bg = new MySprite();
    lesson_bg.init(this.images.get('lesson_bg'));
    lesson_bg.x = lesson_bg.width/2 + 60;
    lesson_bg.y = pic1.height/2;
    this.renderArr.push(lesson_bg);
    this.lesson_bg = lesson_bg;

    //课程信息
    const lesson = new Label();
    lesson.text = this.data.lesson_val;
    lesson.textAlign = 'center';
    lesson.fontSize = 40;
    lesson.fontName = 'BRLNSDB';
    lesson.fontColor = '#ffffff';
    lesson.refreshSize();

    this.lesson = lesson;

    lesson_bg.addChild(lesson);

    const title_bg = new MySprite();
    title_bg.init(this.images.get('title_bg'));
    title_bg.x = this.canvasWidth / 2;
    title_bg.y = title_bg.height/2;
    title_bg.setScaleXY(this.mapScale);
    this.title_bg = title_bg;
    this.renderArr.push(title_bg);

    //初始化字母（组合）信息
    this.initTitle();

    //初始化单词显示
    this.initWord();

    //初始化小手图片
    const mousemove = new MySprite();
    mousemove.init(this.images.get('mousemove'));
    mousemove.x = mousemove.width/2;
    mousemove.y = this.canvasHeight - mousemove.height;

    this.mousemove_cur = mousemove;

    this.renderArr.push(mousemove);

    //初始化小手按下图片
    const mousedown = new MySprite();
    mousedown.init(this.images.get('mousedown'));
    mousedown.x = mousedown.width/2;
    mousedown.y = this.canvasHeight - mousedown.height;
    mousedown.visible = false;

    this.mousedown_cur = mousedown;

    this.renderArr.push(mousedown);
  }

  /**
   * 绘画单词
   */
  drawWordSprite(){

    const getWordSprite = (index) =>{

      //单词背景
      let word_bg = new ShapeRect();

      //单词
      let word_content = this.data.wordArr[index];

      let totalWidth = 0;

      let height = 0;

      let letter_spr_arr = [];

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

        

        //字母
        let letter = word_content.letters[i];

        let colorId = this.getColorId(letter.letter_val);

        let letter_spr = new Label();
        letter_spr.text = letter.letter_val;
        letter_spr.textAlign = 'center';
        letter_spr.fontSize = 60;
        letter_spr.fontName = 'GOTHICB';
        letter_spr.fontColor = this.getColor(colorId);
        //设置不显示
        letter_spr.alpha=0;
        letter_spr.refreshSize();

        letter_spr_arr.push(letter_spr);

        //设置y坐标
        letter_spr.y = letter_spr.height/2;

        height = letter_spr.height;
        totalWidth += letter_spr.width;

        if((i + 1) < word_content.letters.length){
          totalWidth += 5;
        }

        //设置单词未加截完
        this.setWordLoad(index, String(i), false, letter_spr);

        word_bg.addChild(letter_spr);
      }

      let temp_startX = 0;

      //设置所有字母的x坐标
      for(let i = 0; i < letter_spr_arr.length; ++ i){

        let startX = 0;

        if(i == 0){
          startX = letter_spr_arr[i].width/2;
        }
        else{
          temp_startX += letter_spr_arr[i-1].width + 5;
          startX = temp_startX + letter_spr_arr[i].width/2;
        }
        
        letter_spr_arr[i].x = startX;

      }

      word_bg.setSize(totalWidth, height);
      //设置不显示
      word_bg.alpha = 0;
      this.word_height = word_bg.height;
      this.word_arr.push(word_bg);
    };

    //单词个数
    let wordNum = this.data.wordArr.length;

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

      getWordSprite(i);

    }
  }

  /**
   * 初始化单词显示
   */
  initWord(){

    this.drawWordSprite();

    //中心坐标x
    let middleX = this.canvasWidth/2;

    //中心坐标y
    let middleY = (this.canvasHeight - this.top_bg.height)/2;

    //行数
    let rows = 0;

    //列数
    let cols = 0;

    //单词个数
    let wordNum = this.word_arr.length;

    if(wordNum < 4){
      rows = 1;

      cols = wordNum;
    }
    else if(wordNum == 4){
      rows = 2;

      cols = 2;
    }
    else {

      cols = 3;

      rows = Math.floor(wordNum/3);

      if(wordNum % 3 != 0){
        rows += 1;
      }
    }

    //总宽度
    let totalWidth = 0;

    //总高度
    let totalHeight = rows * this.word_height + (rows - 1) * this.interval_height;

    //起始Y坐标
    let startY = (this.canvasHeight - this.top_bg.height - totalHeight) / 2;

    //单词最大宽度
    let word_max_width = 0;

    //计算单词最大宽度
    for(let i = 0; i < wordNum; ++ i){

      let index = i + 1;

      let word_spreat = this.word_arr[i];

      // 如果不是行末尾，计算最大单词宽度
      if(index % cols != 0 && index != wordNum){

        //如果单词宽度大于最大单词宽度，取修改最大单词宽度
        if(word_spreat.width > this.max_word_width){
          this.max_word_width = word_spreat.width;
        }
        
      }
    }

    let row_max_width = 0;

    let temp_row_max_width = 0;

    //计算行最大宽度
    for(let i = 0; i < wordNum; ++ i){

      let index = i + 1;

      let word_spreat = this.word_arr[i];

      // 如果不是行末尾
      if(index % cols != 0 && index != wordNum){

        temp_row_max_width += this.max_word_width + this.interval_width;
        
      }
      // 到最后一个单词
      else if(index % cols != 0 && index == wordNum){

        temp_row_max_width += word_spreat.width;

        if(temp_row_max_width > row_max_width){
          row_max_width = temp_row_max_width;
        }

        temp_row_max_width = 0;
      }
      // 每行显示n个单词
      else if(index % cols == 0){
        temp_row_max_width += word_spreat.width;

        if(temp_row_max_width > row_max_width){
          row_max_width = temp_row_max_width;
        }

        temp_row_max_width = 0;
      }
    }

    console.log('row_max_width', row_max_width);

    //起始X坐标
    let startX = (this.canvasWidth - row_max_width)/2;

    //每行起始坐标
    let row_startX = startX;
    
    for(let i = 0; i < wordNum; ++ i){

      let index = i + 1;

      let word_spreat = this.word_arr[i];

      word_spreat.y = startY;

      word_spreat.x = row_startX;

      // 如果不是行末尾，增加空格
      if(index % cols != 0 && index != wordNum){

        row_startX += this.max_word_width + this.interval_width;
      }
      // 到最后一个单词
      else if(index % cols != 0 && index == wordNum){

        
      }
      // 每行显示n个单词
      else if(index % cols == 0){
        //每一行最后一个单词，高度起始坐标增加
        startY += this.interval_height;

        //下一行X坐标复原
        row_startX = startX;
      }

      this.renderArr.push(word_spreat);
    }
    

  }

  /**
   * 根据字母（组合）获取对应的颜色id
   * @param letter 字母（组合）
   */
  getColorId(letter){

    //默认黑色
    let colorId = "C04";

    for(let i = 0; i < this.data.titleArr.length; ++ i){
      let title = this.data.titleArr[i];

      if(title && title.title_val.toLowerCase() == letter.toLowerCase()){

        if(title.title_color && title.title_color != ""){
          colorId = title.title_color;
        }
        break;
      }
    }

    return colorId;
  }
  

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

    let color = "#000000";

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

    return color;
  }

  /**
   * 初始化字母（组合）显示
   */
  initTitle(){

    let totalWidth = 0;

    //初始化标题字母（组合）信息
    for(let i = 0; i < this.data.titleArr.length; ++ i){
      
      let title = this.data.titleArr[i];
     
      if(title.title_val){
        let titleSp = this.getTitleSprite(title);
        
        this.title_arr.push(titleSp);

        totalWidth += titleSp.width;

        if(i < this.data.titleArr.length - 1){
          totalWidth += 15;
        }
      }
    }

    let title_bg_width = this.title_bg.width;

    if(totalWidth >= this.title_bg.width){

      title_bg_width = totalWidth + 100;

      this.title_bg.scaleX=title_bg_width/this.title_bg.width;
   
    }
   
    //重新设置字母（组合）的坐标
    let titleStartX = (title_bg_width - totalWidth)/2 - title_bg_width/2;

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

      let title = this.title_arr[i];

      title.x = titleStartX + title.width/2;
      
      //父类拉伸后，子类不拉伸
      title.scaleX /= this.title_bg.scaleX;

      titleStartX += title.width;

      if(i < this.title_arr.length - 1){
        titleStartX += 15;
      }

      this.title_bg.addChild(title);
    }
    
  }

  getTitleSprite(titleItem){

    const title = new Label();
    title.text = titleItem.title_val;
    title.textAlign = 'center';
    title.fontSize = 50;
    title.fontName = 'BRLNSDB';
    title.fontColor = '#ffffff';
    title.refreshSize();

    return title;
  }

  mapDown(event) {

    if (!this.canTouch) {
      return;
    }
    
    //增加鼠标点击事件
    this.playAudio("click");

    this.mousemove_cur.visible = false;
    this.mousedown_cur.x=this.mousemove_cur.x;
    this.mousedown_cur.y=this.mousemove_cur.y;
    this.mousedown_cur.visible = true;
    
    if (this.checkClickTarget(this.lesson_bg)) {
      this.playAudio(this.data.lesson_audio_url);
      return;
    }

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

      let title = this.title_arr[i];

      if (this.checkClickTarget(title)) {
        this.playAudio(this.data.titleArr[i].title_audio_url);
        return;
      }
    }

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

      //获取是否加载完成
      let loaded = this.getWordLoaded(String(i));
      console.log('word loaded', loaded);
      //未加载，不触发音效，加载单词
      if(!loaded){
        let letters = this.getLetterSpriteFromWordLoaded(String(i));

        for(let key in letters){

          let loaded = letters[key].loaded;

          let letter_spr = letters[key].letter;

          let letter_audio_url = this.data.wordArr[i].letters[key].letter_audio_url;

          console.log('letter load', loaded);
          //加载完成，跳过
          if(loaded){

            //检查是否点了该字母
            if (this.checkClickTarget(letter_spr)) {
              this.playAudio(letter_audio_url);
              return;
            }
            continue;
          }

          

          //设置显示
          letter_spr.alpha = 1;
          //设置加载完成
          letters[key].loaded = true;

          
          //播放音效
          this.playAudio(letter_audio_url);

          this.checkWordLoaded(String(i));

          return;
        }

        break;
      }

      let word = this.word_arr[i];

      if (this.checkClickTarget(word)) {
        this.playAudio(this.data.wordArr[i].word_audio_url);
        return;
      }
    }


  }

  mapMove(event) {

      if(this.mousemove_cur){
        this.mousemove_cur.x = this.mx + this.mousemove_cur.width/2 - 17;
    
        this.mousemove_cur.y = this.my + this.mousemove_cur.height/2 - 17;
      }
      
  }

  mapUp(event) {

    this.mousemove_cur.visible = true;

    this.mousedown_cur.visible = false;
  }



  update() {

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



    this.updateArr(this.renderArr);


  }

}
