/**
 * @file MyCocosSceneComponent.ts
 * @description 基础场景组件，提供了场景初始化、资源预加载、屏幕适配等基础功能
 */

import { defaultData } from "../script/defaultData";

/**
 * @class MyCocosSceneComponent
 * @extends cc.Component
 * @description 基础场景组件类，继承自 cc.Component，提供场景通用功能
 */
export class MyCocosSceneComponent extends cc.Component {

  /**
   * @description 生命周期函数，组件加载时调用
   * @override
   */
  onLoad() {
    this.initSceneData();
    this.initSize();
  }

  /** @private 图片资源列表 */
  _imageResList = null;
  /** @private 音频资源列表 */
  _audioResList = null;
  /** @private 动画资源列表 */
  _animaResList = null;
  
  /**
   * @description 初始化场景数据，创建资源列表数组
   * @private
   */
  initSceneData() {
    this._imageResList = [];
    this._audioResList = [];
    this._animaResList = [];
  }

  /** @private 设计分辨率 */
  _designSize = null;
  /** @private 屏幕分辨率 */
  _frameSize = null;
  /** @private 场景中常用缩放（取小值） */
  _mapScaleMin = null;
  /** @private 场景中常用缩放（取大值） */
  _mapScaleMax = null;
  /** @private cocos 自缩放（较少用到） */
  _cocosScale = null;
  
  /**
   * @description 初始化屏幕尺寸和缩放比例，处理屏幕适配
   * @private
   */
  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;

    cc.director['_scene'].width = frameSize.width;
    cc.director['_scene'].height = frameSize.height;
  }

  /** @public 游戏数据对象 */
  data = null;

  /**
   * @description 生命周期函数，组件启动时调用
   * @override
   */
  start() {
    if (window && (<any>window).courseware && (<any>window).courseware.getData) {
      (<any>window).courseware.getData((data) => {
        this.log('data:' + data);
        this.data = data || this.getDefaultData();
        this.data = JSON.parse(JSON.stringify(this.data));
        this.preloadItem();
      })
    } else {
      this.data = this.getDefaultData();
      this.preloadItem();
    }
  }

  /**
   * @description 获取默认游戏数据
   * @returns {Object} 默认游戏数据对象
   */
  getDefaultData() {
    return defaultData;
  }

  /**
   * @description 预加载所有资源项
   */
  preloadItem() {
    this.addPreloadImage();
    this.addPreloadAudio();
    this.addPreloadAnima();
    this.preload();
  }

  /**
   * @description 添加需要预加载的图片资源
   * @virtual 子类需要重写此方法
   */
  addPreloadImage() {
  }

  /**
   * @description 添加需要预加载的音频资源
   * @virtual 子类需要重写此方法
   */
  addPreloadAudio() {
  }

  /**
   * @description 添加需要预加载的动画资源
   * @virtual 子类需要重写此方法
   */
  addPreloadAnima() {
  }

  /**
   * @description 执行资源预加载
   * @private
   */
  preload() {
    const preloadArr = this._imageResList.concat(this._audioResList).concat(this._animaResList);
    cc.assetManager.loadAny(preloadArr, null, null, (err, data) => {

      if (window && window["air"]) {
        // window["air"].onCourseInScreen = (next) => {
        //   window["air"].isCourseInScreen = true;
        //   this.onLoadEnd();
        //   next();
        // };
        this.onLoadEnd();
        window["air"].hideAirClassLoading();
      } else {
        this.onLoadEnd();
      }

      cc.debug.setDisplayStats(false);
    });
  }

  /**
   * @description 日志输出函数，优先使用 middleLayer 组件的 log 方法，如果不存在则使用 cc.log
   * @param {string} str 要输出的日志内容
   */
  log (str) {
    const node = cc.find('middleLayer');
    if(node){
      node.getComponent('middleLayer').log(str);
    }else{
      cc.log(str);
    }
  }

  /**
   * @description 资源加载完成后的回调函数
   * @virtual 子类需要重写此方法
   */
  onLoadEnd() {
  
  }















  
  // ------------------------------------------------
  /**
   * @description 根据资源名称获取精灵节点
   * @param {string} resName 资源名称
   * @returns {cc.Node} 创建的精灵节点
   */
  getSprNode(resName) {
    const sf = cc.find('Canvas/res/img/' + resName).getComponent(cc.Sprite).spriteFrame;
    const node = new cc.Node();
    node.addComponent(cc.Sprite).spriteFrame = sf;
    return node;
  }


  /**
   * @description 根据URL加载精灵帧
   * @param {string} url 图片URL
   * @param {Function} cb 加载完成后的回调函数，参数为加载的精灵帧
   */
  getSpriteFrimeByUrl(url, cb) {
    cc.loader.load({ url }, (err, img) => {
      const spriteFrame = new cc.SpriteFrame(img)
      if (cb) {
        cb(spriteFrame);
      }
    })
  }

  /**
   * @description 根据URL创建精灵节点
   * @param {string} url 图片URL
   * @param {Function} cb 创建完成后的回调函数，参数为创建的节点
   */
  getSprNodeByUrl(url, cb) {
    const node = new cc.Node();
    const spr = node.addComponent(cc.Sprite);
    this.getSpriteFrimeByUrl(url, (sf) => {
      spr.spriteFrame = sf;
      if (cb) {
        cb(node);
      }
    })
  }

  /**
   * @description 根据URL播放音频
   * @param {string} audio_url 音频URL
   * @param {Function} cb 音频播放完成后的回调函数
   */
  playAudioByUrl(audio_url, cb = null) {
    if (audio_url) {
      cc.assetManager.loadRemote(audio_url, (err, audioClip) => {
        const audioId = cc.audioEngine.play(audioClip, false, 0.8);
        if (cb) {
          cc.audioEngine.setFinishCallback(audioId, () => {
            cb();
          });
        }
      });
    }else{
      cb && cb();
    }
  }
}