/**
 * @description 按路径行走
 * props 方式一： 变量注释
 */
class PathMotion extends THING.Component {
  constructor() {
    super()

    /**
     * @typedef {object} widget
     * @property {string} [name=路径]
     * @property {string} [type=text]
     * @property {string} [propertyPanel=public]
     */
    this.path = []

    /**
     * @typedef {object} widget
     * @property {string} [type=slider]
     * @property {string} [name=速度]
     * @property {number} [min=0.1]
     * @property {number} [max=5]
     * @property {number} [step=0.1]
     */
    this.speed = 0.1

    /**
     * @typedef {object} widget
     * @property {string} [type=switch]
     * @property {string} [name=循环]
     */
    this.loop = true

    /**
     * @typedef {object} widget
     * @property {string} [type=switch]
     * @property {string} [name=自动]
     */
    this.auto = true
  }

  onStart() {
    this.object.waitForComplete().then(() => {
      this.isMove = false
      this.tempPos = this.object.position
      this._initParam()
    })
  }

  onImport(param) {
    this.speed = param.speed.value
    this.auto = param.auto.value
    this.path = eval(param.path.value) || []
  }

  _initParam() {
    try {
      this.path = eval(this.props.path.value)
      // this.path.length > 0 && (this.object.position = this.path[0])
      if (this.path.length > 0) {
        this.path = this._checkPath(this.path)
        //  主角，这里就不用move了
        if (this.object.isLead) return
        this.auto && this.move()
      }
    } catch (error) {
      console.error(`预制件 : ${this.object.parent.name} 参数异常`, this.object)
    }
  }

  /**
   * 指定的路径，也许第一个点，不是对象当前的站立点，避免坐标变化异常，把当前站立点加入到path中
   * @param {Array} path
   */
  _checkPath(path) {
    try {
      if (!THING.MathUtils.equalsVector(path[0], this.tempPos)) {
        path.unshift(this.tempPos)
      }
      return path
    } catch (error) {
      console.error(
        `预制件 : ${this.object.parent.name} 输入config.path 参数异常`,
        this.object
      )
      return []
    }
  }
  getTotalTime(path, speed) {
    let td = 0
    for (let i = 0; i < path.length - 1; i++) {
      const d = THING.Math.vec3.distance(path[i], path[i + 1])
      td += d
    }
    td = td === 0 ? 0.01 : td // movepath时间不能是0

    if (Number.isNaN(td)) {
      console.error(
        `预制件 : ${this.object.parent.name} 路径或速度解析异常`,
        this.object
      )
      return 0.01
    }
    return Number(td / Math.abs(speed)) * 100
  }

  /**
   * @public
   * @description 根据路径行走
   * @param {Array} path 行走路径
   */
  move(config = {}) {
    const path =
      config && config.path && config.path.length > 0
        ? this._checkPath(config.path)
        : this.path
    this.stop()
    if (path.length < 1) {
      console.error(`${this.object.parent.name}:行走路径点少于1个, 无法移动!`)
      return
    }

    this.isMove = true
    const speed = config && config.speed ? config.speed : this.speed
    const loop = config && config.loop ? config.loop : this.loop
    const t = this.getTotalTime(path, speed)
    const { object: o } = this

    this.object.movePath(path, {
      closure: true,
      time: t,
      times: loop ? Infinity : 1, // 循环次数用times。没有LoopType.Once了。。。
      start: () => {
        o.baseAnimation && o.baseAnimation.play()
      },
      stop: () => {
        o.baseAnimation && o.baseAnimation.stop()
      },
      complete: () => {
        o.baseAnimation && o.baseAnimation.stop()
      },
      next: function (ev) {
        const quaternion = o.getWorldQuaternionFromTarget(ev.to)
        o.lerp.to({
          to: {
            quaternion,
          },
          time: 100, // fix: 速度过快有 time 值时, destroy() boy 会报错
        })
      },
    })
  }
  /**
   * @public
   */
  stop() {
    this.isMove = false
    const { object } = this
    object.stopMoving()
    object.baseAnimation && object.baseAnimation.stop()
    this.object.position = this.tempPos
  }
  /**
   * @public
   */
  resume() {
    const { object } = this
    object.resumeMoving()
    object.baseAnimation && object.baseAnimation.play()
  }
  /**
   * @public
   */
  pause() {
    const { object } = this
    object.pauseMoving()
    object.baseAnimation && object.baseAnimation.stop()
  }
}
