import { asyncPlayDragonBoneAnimation } from "./util";

const { ccclass, property } = cc._decorator;

@ccclass
export default class LoadingLayer extends cc.Component {

  ctor() {
  }

  // 生命周期 onLoad
  onLoad() {
    // this.initSize();
  }

  _designSize;  // 设计分辨率
  _frameSize;  // 屏幕分辨率
  _mapScaleMin;  // 场景中常用缩放（取大值）
  _mapScaleMax;  // 场景中常用缩放（取小值）
  _cocosScale;  // cocos 自缩放 （较少用到）
  initSize() {
    // 注意cc.winSize只有在适配后(修改fitHeight/fitWidth后)才能获取到正确的值,因此使用cc.getFrameSize()来获取初始的屏幕大小
    let screen_size = cc.view.getFrameSize().width / cc.view.getFrameSize().height
    let design_size = cc.Canvas.instance.designResolution.width / cc.Canvas.instance.designResolution.height
    let f = screen_size >= design_size
    cc.Canvas.instance.fitHeight = f
    cc.Canvas.instance.fitWidth = !f

    const frameSize = cc.view.getFrameSize();
    this._frameSize = frameSize;

    this._designSize = cc.view.getDesignResolutionSize();

    let sx = cc.winSize.width / frameSize.width;
    let sy = cc.winSize.height / frameSize.height;
    this._cocosScale = Math.min(sx, sy);

    sx = frameSize.width / this._designSize.width;
    sy = frameSize.height / this._designSize.height;
    this._mapScaleMin = Math.min(sx, sy) * this._cocosScale;
    this._mapScaleMax = Math.max(sx, sy) * this._cocosScale;
  }


  // 生命周期 start
  async start() {
    this.updateLabel('创建房间中');
    this.progressTo(0.1, 1);
    await this.asyncDelay(1);
    this.updateLabel('匹配小伙伴中');
  }

  async initView() {
    this.setMaxPlayerNumber(5);
  }

  _maxPlayerNum;
  setMaxPlayerNumber(number) {
    this._maxPlayerNum = number;
  }

  _playerList;
  addPlayer(name, isSelf, headUrl, uuid) {
    if (!this._playerList) {
      this._playerList = [];
    }
    if (this._playerList.find(player => player.uuid == uuid)) {
      return;
    }
    this._playerList.push({ name, isSelf, headUrl, uuid });
    console.log('name = ' + name);
    const layout = cc.find('layout', this.node);
    const headNode = cc.instantiate(cc.find('head', this.node));
    headNode.x = 0;
    headNode.y = 0;
    headNode.active = true;
    const frameSelf = cc.find('frame_self', headNode);
    if (!isSelf) {
      frameSelf.opacity = 0;
    }

    const nameLabel = cc.find('name', headNode);
    nameLabel.getComponent(cc.Label).string = name;

    const headImg = cc.find('mask/headImg', headNode);
    this.loadSpriteByUrl(headImg, headUrl, () => {
      const scale = Math.max(
        headImg.parent.width / headImg.width,
        headImg.parent.height / headImg.height
      );
      headImg.scale = scale;
    });

    if (this._playerList.length == 1) {
      cc.find('left', this.node).addChild(headNode);
    } else {
      cc.find('right', this.node).addChild(headNode);
      const vs = cc.find('vs', this.node);
      asyncPlayDragonBoneAnimation(vs, 'normal', 1);
      this.playLocalAudio('match');
    }

    const rate = Math.min(1, this._playerList.length / this._maxPlayerNum);

    if (rate == 1) {
      this.updateLabel('同步中');
    }

    this.progressTo(rate, 3);
  }

  _onLoadFinishFunc;
  onLoadFinished(func) {
    this._onLoadFinishFunc = func;
  }

  async asyncDelay(time) {
    return new Promise((resolve, reject) => {
      try {
        this._timeoutIds.push(setTimeout(() => {
          resolve(null);
        }, time * 1000));
      } catch (e) {
        reject(e);
      }
    });
  }

  updateLabel(str) {
    const label = cc.find('label', this.node).getComponent(cc.Label);
    if (label['tweenAction']) {
      label['tweenAction'].stop();
    }
    label['tweenAction'] = cc.tween(label)
      .set({ string: `${str}` })
      .delay(0.4)
      .set({ string: `${str}.` })
      .delay(0.4)
      .set({ string: `${str}..` })
      .delay(0.4)
      .set({ string: `${str}...` })
      .delay(0.4)
      .union()
      .repeatForever()
      .start();
  }

  _maxRate = 0;
  progressTo(rate, time) {
    this._maxRate = Math.max(this._maxRate, rate);
    const duration = Math.max(time + this.RandomInt(-1, 1), 1);
    const progress = cc.find('progressBar', this.node).getComponent(cc.ProgressBar);
    if (progress['tweenAction']) {
      progress['tweenAction'].stop();
    }
    const easingList = [
      'linear',
      'quadInOut',
      'cubicInOut',
    ];
    progress['tweenAction'] = cc.tween(progress)
      .to(duration, { progress: this._maxRate }, { easing: easingList[this.RandomInt(easingList.length)] })
      .call(() => {
        if (rate == 1) {
          if (this._onLoadFinishFunc) {
            this._onLoadFinishFunc();
          }
          this.node.active = false;
        }
      })
      .start();
  }

  RandomInt(a, b = 0) {
    let max = Math.max(a, b);
    let min = Math.min(a, b);
    return Math.floor(Math.random() * (max - min) + min);
  }










  // ------------------------------------------------
  loadSpriteByUrl(node, url, cb) {
    cc.loader.load({ url }, (err, img) => {
      if (!node) {
        cb && cb();
      }
      const spriteFrame = new cc.SpriteFrame(img)
      const spr = node.getComponent(cc.Sprite);
      spr.spriteFrame = spriteFrame;
      cb && cb();
    });
  }

  currentPlayedAudioId;
  stopCurrentPlayedAudio() {
    if (this.currentPlayedAudioId !== null) {
      cc.audioEngine.stop(this.currentPlayedAudioId);
      this.currentPlayedAudioId = null;
    }
  }
  playEffect(name, cb) {
    this.stopCurrentPlayedAudio();
    const audioNode = cc.find(`audios/${name}`);
    const audioClip = audioNode.getComponent(cc.AudioSource).clip;
    const audioId = cc.audioEngine.play(audioClip, false, 0.8);
    this.currentPlayedAudioId = audioId;
    if (cb) {
      cc.audioEngine.setFinishCallback(audioId, cb);
    }
  }
  playAudioByUrl(audio_url, cb = null) {
    if (!audio_url) {
      if (cb) {
        cb();
      }
      return;
    }
    this.stopCurrentPlayedAudio();
    cc.assetManager.loadRemote(audio_url.toLowerCase(), (err, audioClip) => {
      const audioId = cc.audioEngine.play(audioClip, false, 0.8);
      this.currentPlayedAudioId = audioId;
      if (cb) {
        cc.audioEngine.setFinishCallback(audioId, cb);
      }
    });
  }

  playLocalAudio(name) {
    return new Promise((resolve, reject) => {
      this.stopCurrentPlayedAudio();
      const audioNode = cc.find(`res/${name}`, this.node);
      if (!audioNode) {
        resolve(null);
        return;
      }
      const audioClip = audioNode.getComponent(cc.AudioSource).clip;
      const audioId = cc.audioEngine.play(audioClip, false, 0.8);
      this.currentPlayedAudioId = audioId;

      cc.audioEngine.setFinishCallback(audioId, () => {
        resolve(null);
      });
    });
  }

  _timeoutIds = [];
  _intervalIds = [];
  // 生命周期
  onDestroy() {
    this._timeoutIds.forEach(id => {
      clearTimeout(id);
    });
    this._intervalIds.forEach(id => {
      clearInterval(id);
    });
  }
}
