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

import {
  getAngleByPos,
  MySprite,
  getPosByAngle,
  Label,
  MyAnimation,
  moveItem, randomSortByArr, scaleItem, rotateItem, tweenChange, hideItem, showItem, BitMapLabel, ShapeRect, RichTextLemon
} from './Unit';
import res from './resources';

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

import * as _ from 'lodash';
import TWEEN from '@tweenjs/tween.js';
import {del} from "selenium-webdriver/http";



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




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

  canvasBaseW = 1280;
  canvasBaseH = 720;

  ctx;
  fps = 0;
  frametime = 0;  // 上一帧动画的时间，   两帧时间差


  mx;
  my; // 点击坐标



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

  // 声音

  bgAudio = new Audio();
  successAudio = new Audio();
  wrongAudio = new Audio();
  flyAudio = new Audio();


  images = new Map();

  animationId: any;
  winResizeEventStream = new Subject();


  audioObj = {};
  renderArr;
  mapScale = 1;

  canvasLeft;
  canvasTop;



  // ------

  KEY = 'dfzx_04';
  unitLabel;
  titleLabel;

  bottomArr = [];



  canTouch = true;
  picArr = [];
  craneArr = [];
  posArr = [
    [163, 502],
    [238, 244],
    [492, 159],
    [573, 587],
    [723, 378],
    [830, 120],
    [1053, 254],
    [1105, 555],

  ];


  maskLayer;
  paper;
  closeBtn;
  randomPicArr;
  randomPicIndex = 0;
  sprArr = [];
  topArr = [];
  curData;
  firstTouch;



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


  ngOnInit() {


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

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

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

      this.initDefaultData();



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

    }, this.KEY);




  }

  ngOnDestroy() {
    window.cancelAnimationFrame(this.animationId);


    for (let key in this.audioObj) {
      if (this.audioObj[key]) {
        this.audioObj[key].pause();
      }
    }
  }

  initData() {

    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.mapScale = this.canvasWidth / this.canvasBaseW;
    // this.mapScale = this.canvasHeight / this.canvasBaseH;
    this.renderArr = [];

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



    this.canTouch = true;
    // this.craneArr = [];
    // this.picArr = this.data.contentObj.picArr;
    // if (!this.picArr) {
    //   this.picArr = [];
    // } else {
    //
    //   for (let i = 0; i < this.picArr.length; i++) {
    //     this.picArr[i].id = i;
    //   }
    // }
    //
    // this.firstTouch = true;

    // // this.boxPicArr = this.picArr.concat();
    // // this.batPicArr = this.picArr.concat();
    // this.boxPicArr = [];
    // this.batPicArr = [];
    // this.lightIndexArr = [];
    // this.initBoxPicArr();
  }





  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 picArr = contentObj.picArr;
    if (picArr) {

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

        const audioUrl = picArr[i].audio_url;
        if (audioUrl) {
          const audio = new Audio();
          audio.src = audioUrl;
          audio.load();
          this.audioObj[audioUrl] = audio;
        }

      }
    }


    // this.flyAudio.src = 'assets/bat-mail/music/fly.mp3';
    // this.flyAudio.load();
    // this.flyAudio.loop = true;
    // this.flyAudio.volume = 0.5;
    //
    // 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.successAudio.src = 'assets/bat-mail/music/success.mp3';
    // this.successAudio.load();
    //



  }

  initImg() {

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

    const picUrl = this.data.contentObj.pic_url;
    if (picUrl) {
      this.rawImages.set(picUrl, picUrl);
    }

    // const picArr = this.data.contentObj.picArr;
    // if (picArr) {
    //
    //   for (let i = 0; i < picArr.length; i++) {
    //
    //     const picUrl = picArr[i].pic_url;
    //     if (picUrl) {
    //       this.rawImages.set(picUrl, picUrl);
    //     }
    //
    //   }
    // }






    // 预加载资源

    this.loadResources().then(() => {

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

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

  }



  initDefaultData() {

    if (!this.data.contentObj.unit) {
     this.data.contentObj.unit = 'Unit 1';
    }
    if (!this.data.contentObj.title) {
      this.data.contentObj.title = 'Hello';
    }
    if (!this.data.contentObj.pic_url) {
      this.data.contentObj.pic_url = 'assets/default/logo.png';
    }


  }




  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;



    // console.log('this.ctx.canvas w: ', this.ctx.canvas.width);
    // console.log('this.ctx.canvas h: ', this.ctx.canvas.height);
  }


  initView() {

    this.initBg();
    this.initUnit();
    this.initTitle();

    this.initLogo();

    this.showAnima();
    // this.initItem();
  }

  showAnima() {

    this.unitLabel.alpha = 0;
    this.unitLabel.bg.alpha = 0;
    this.titleLabel.y = -this.titleLabel.fontSize;


    const showUnit = () => {
      tweenChange(this.unitLabel, {alpha: 1}, 0.7, null, TWEEN.Easing.Cubic.Out, (item, progress) => {
        this.unitLabel.bg.alpha = this.unitLabel.alpha;
      });
    };

    const showTitle = () => {
      moveItem(this.titleLabel, this.titleLabel.x, this.titleLabel.baseY, 1, () => {
        showUnit();
      }, TWEEN.Easing.Bounce.Out);
    };

    showTitle();
  }

  initBg() {

    this.bottomArr = [];

    const bg = new MySprite(this.ctx);
    bg.init(this.images.get('bg'));
    bg.x = this.canvasWidth / 2;
    bg.y = this.canvasHeight / 2;
    const sx = this.canvasWidth / bg.width;
    const sy = this.canvasHeight / bg.height;
    const s = Math.max(sx, sy);
    bg.setScaleXY(s);
    this.bottomArr.push(bg);
  }


  initUnit() {

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


    const y = 50;

    const labelBg = new Label(this.ctx);
    labelBg.text = this.data.contentObj.unit;
    labelBg.setScaleXY(this.mapScale);
    labelBg.fontSize = 55;
    labelBg.fontColor = '#c37800';
    labelBg.fontName = 'BRLNSDB_1';
    labelBg.textAlign = 'center';
    labelBg.x = this.canvasWidth / 2;
    labelBg.y = (y + 5) * this.mapScale;
    labelBg.setShadow(0, 3, 2, 'rgba(0, 0, 0, 0.35)');


    const label = new Label(this.ctx);
    label.text = this.data.contentObj.unit;
    label.setScaleXY(this.mapScale);
    label.fontSize = 55;
    label.fontColor = '#ffd300';
    label.fontName = 'BRLNSDB_1';
    label.textAlign = 'center';
    label.x = this.canvasWidth / 2;
    label.y = y * this.mapScale;
    label['bg'] = labelBg;

    this.renderArr.push(labelBg);
    this.renderArr.push(label);


    this.unitLabel = label;
  }


  initTitle() {

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


    const label = new Label(this.ctx);
    label.text = this.data.contentObj.title;
    label.setScaleXY(this.mapScale);
    label.fontSize = 220;
    label.fontColor = '#ffffff';
    label.fontName = 'CooperBlackStd';
    label.textAlign = 'center';
    label.x = this.canvasWidth / 2;
    label.y = this.canvasHeight / 2 - 20 * this.mapScale;
    label.setOutline(20, '#ff7600');

    // this.renderArr.push(label);



    const titleText = new RichTextLemon(this.ctx);
    titleText.init();
    titleText.fontSize = 125 * this.mapScale;
    titleText.disH = (10) * this.mapScale;
    titleText.fontColor = '#ffffff';
    titleText.fontName = 'CooperBlackStd';
    // titleText.fontName = 'Verdana';
    titleText.textAlign = 'center';
    titleText.text = this.data.contentObj.title;
    titleText.y = this.canvasHeight / 2 - titleText.fontSize / 2 -  this.canvasHeight / 15; // * this.mapScale - titleText.fontSize * this.mapScale; // - titleText.textH - titleText.fontSize;
    // titleText.setScaleXY(this.mapScale);
    titleText.width = this.canvasWidth / 1.6;
    // titleText.fontWeight = 900;
    titleText.setOutline(20, '#ff7600');


    titleText.x = this.canvasWidth / 2; // - titleText.width * titleText.scaleX / 2;
    titleText['baseY'] = titleText.y;

    // this.titleText = titleText;

    this.renderArr.push(titleText);

    this.titleLabel = titleText;

  }


  initLogo() {

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


    const logoW = 320 * this.mapScale;
    const logoH = 220 * this.mapScale;

    const offSet = 20 * this.mapScale;

    const logo = new MySprite(this.ctx);
    logo.init(this.images.get(picUrl));
    logo.setScaleXY(this.mapScale);
    logo.x = this.canvasWidth - logoW / 2 - offSet;
    logo.y = this.canvasHeight - logoH / 2 - offSet;

    const sx = logoW / logo.width;
    const sy = logoH / logo.height;
    const s = Math.min(sx, sy);
    logo.setScaleXY(s);

    this.renderArr.push(logo);

  }



  initItem() {

    this.initPaper();
    this.initCrane();


    // this.showStartAnima();


  }

  initCrane() {

    this.craneArr = [];
    this.sprArr = [];
    this.randomPicArr = randomSortByArr(this.picArr);

    for (let i = 0; i < this.posArr.length; i++) {
      const crane = this.getCrane();
      crane.x = this.posArr[i][0] * this.mapScale;
      crane.y = this.posArr[i][1] * this.mapScale;

      crane['baseX'] = crane.x;
      crane['baseY'] = crane.y;

      crane.y -= this.canvasHeight;

      crane['data'] = this.getCraneData();
      this.craneArr.push(crane);
    }
  }

  showStartAnima() {

    const arr = this.craneArr;
    const moveTime = 2;
    const maxDelayTime = 0.7;
    let delayTime;
    for (let i = 0; i < arr.length; i++) {
      const crane = arr[i];
      // crane.baseY = crane.y;
      // crane.y -= this.canvasHeight;

      delayTime = Math.random() * maxDelayTime;
      setTimeout(() => {

        moveItem(crane, crane.x, crane.baseY, moveTime, null, TWEEN.Easing.Elastic.Out);

      }, delayTime * 1000);
    }

    this.canTouch = false;

    setTimeout(() => {
      this.canTouch = true;
    }, (moveTime + maxDelayTime) * 1000);
  }


  getCrane() {

    const crane = new MySprite(this.ctx);
    const randomId = Math.ceil( Math.random() * 5 );
    crane.init(this.images.get('crane-' + randomId));
    crane.x = this.canvasWidth / 2;
    crane.y = this.canvasHeight / 2;
    crane.setScaleXY(this.mapScale);
    this.renderArr.push(crane);
    return crane;
  }

  getCraneData() {

    const picData = this.randomPicArr[this.randomPicIndex];
    const data = {};

    const spr = new MySprite(this.ctx);
    spr.init(this.images.get(picData.pic_url));
    this.sprArr.push(spr);
    spr.visible = false;
    spr.x = this.canvasWidth / 2;
    spr.y = this.canvasHeight / 2 - 8 * this.mapScale;
    const sx = (this.paper.width - 100) * this.mapScale / spr.width;
    const sy = (this.paper.height - 100) * this.mapScale / spr.height;
    const s = Math.min(sx, sy);
    spr.setScaleXY(s);
    data['spr'] = spr;


    const audio = this.audioObj[picData.audio_url];
    data['audio'] = audio;


    this.randomPicIndex ++;
    if (this.randomPicIndex >= this.randomPicArr.length) {
      this.randomPicIndex = 0;
    }

    return data;
  }


  initPaper() {


    this.topArr = [];

    const maskLayer = new ShapeRect(this.ctx);
    maskLayer.setSize(this.canvasWidth, this.canvasHeight);
    maskLayer.fillColor = '#000000';
    maskLayer.alpha = 0.5;
    this.maskLayer = maskLayer;
    this.topArr.push(maskLayer);


    const paper = new MySprite(this.ctx);
    paper.init(this.images.get('white-bg'));
    paper.x = this.canvasWidth / 2;
    paper.y = this.canvasHeight / 2;
    paper.setScaleXY(this.mapScale);
    this.paper = paper;
    this.topArr.push(paper);


    const offX = 35;
    const offY = 35;
    const closeBtn = new MySprite(this.ctx);
    closeBtn.init(this.images.get('close-btn'));
    closeBtn.setScaleXY(this.mapScale);
    closeBtn.x = this.paper.x + (this.paper.width / 2 - offX) * this.paper.scaleX;
    closeBtn.y = this.paper.y - (this.paper.height / 2 - offY) * this.paper.scaleY;
    this.closeBtn = closeBtn;
    // this.topArr.push(closeBtn);



    maskLayer.visible = paper.visible = this.closeBtn.visible = false;
  }





  mapDown(event) {


    // if (this.startMusicFlag) {
    //   this.bgAudio.play();
    //   this.startMusicFlag = false;
    // }

    if (!this.canTouch) {
      return;
    }

    if (this.firstTouch) {
      this.firstTouch = false;
      this.showStartAnima();
      return;
    }

    if (this.maskLayer.visible) {

      if (this.checkClickTarget(this.closeBtn)) {
        this.hidePic();
        return;
      }

      if (this.checkClickTarget(this.paper)) {
        this.showPicSound();
      } else {
        this.hidePic();
      }

      return;

    }


    for (let i = 0; i < this.craneArr.length; i++) {
      if (this.checkClickTarget(this.craneArr[i])) {
        this.clickedCrane(this.craneArr[i]);
        return;
      }
    }
  }



  mapMove(event) {


  }

  mapUp(event) {


  }


  addCrane() {

    const crane = this.getCrane();
    crane.x = this.mx;
    crane.y = this.my;

    console.log('_x: ', this.mx / this.mapScale);
    console.log('_y: ', this.my / this.mapScale);

  }


  clickedCrane(crane) {

    this.showPic(crane);
  }

  showPic(crane) {

    const data = crane.data;
    this.curData = data;

    const spr = data.spr;
    const audio = data.audio;

    if (audio) {

      // if (this.firstAudio) {
      //   this.firstAudio = true;
      //   setTimeout(() => {
      //     audio.play();
      //   }, 1000);
      // } else {
        audio.play();
      // }

    }

    spr.visible = true;


    this.maskLayer.visible = this.paper.visible = this.closeBtn.visible = true;
  }

  hidePic() {

    this.curData.spr.visible = false;
    this.maskLayer.visible = this.paper.visible = this.closeBtn.visible = false;

  }


  showPicSound() {
    if (this.curData && this.curData.audio) {
      this.curData.audio.play();
    }
  }



  update() {

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


    TWEEN.update();

    this.updateArr(this.bottomArr);
    this.updateArr(this.renderArr);
    // this.updateArr(this.topArr);
    // this.updateArr(this.sprArr);
    // this.closeBtn.update(this);

  }

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





  initListener() {

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




    if (this.IsPC()) {

      this.canvas.nativeElement.addEventListener('mousedown', (event) => {

        setMxMyByMouse(event);
        this.mapDown(event);
      });

      this.canvas.nativeElement.addEventListener('mousemove', (event) => {

        setMxMyByMouse(event);
        this.mapMove(event);
      });

      this.canvas.nativeElement.addEventListener('mouseup', (event) => {

        setMxMyByMouse(event);
        this.mapUp(event);
      });


      const setMxMyByMouse = (event) => {

        this.mx = event.offsetX;
        this.my = event.offsetY;
      };



    } else {

      this.canvas.nativeElement.addEventListener('touchstart', (event) => {

        setMxMyByTouch(event);
        this.mapDown(event);
      });

      this.canvas.nativeElement.addEventListener('touchmove', (event) => {
        setMxMyByTouch(event);
        this.mapMove(event);
      });

      this.canvas.nativeElement.addEventListener('touchend', (event) => {
        setMxMyByTouch(event);
        this.mapUp(event);
      });

      this.canvas.nativeElement.addEventListener('touchcancel', (event) => {
        setMxMyByTouch(event);
        this.mapUp(event);
      });


      const setMxMyByTouch = (event) => {

        // console.log('in 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 setParentOffset = () => {

        const rect = this.canvas.nativeElement.getBoundingClientRect();
        this.canvasLeft = rect.left;
        this.canvasTop = rect.top;
      };
    }



  }

  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 => this.images.set(key, img))
        .catch(err => console.log(err));
      pr.push(p);
    });
    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;
    });
  }


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



  checkClickTarget(target) {

    const rect = target.getBoundingBox();

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

  getWorlRect(target) {

    let rect = target.getBoundingBox();

    if (target.parent) {

      const pRect = this.getWorlRect(target.parent);
      rect.x += pRect.x;
      rect.y += pRect.y;
    }
    return rect;
  }

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

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

}
