/**
 * @fileoverview 递归子组件，用于显示节点树
 */
Component({
  data: {
    ctrl: {}, // 控制信号
    nodes: [],
    // #ifdef MP-WEIXIN
    isiOS: wx.getDeviceInfo().system.includes('iOS')
    // #endif
  },
  properties: {
    childs: {
      type: Array,
      value: [],
      observer (nodes) {
        const data = {}
        function diff (a, b, path) {
          let alen = a.length
          // 列表变短，将多余的部分清空
          while (alen > b.length) {
            if (Object.keys(a[alen - 1]).length !== 0) {
              data[path + '[' + (alen - 1) + ']'] = {}
            }
            alen -= 1
          }
          // 列表变长，插入新增的部分
          while (alen < b.length) {
            data[path + '[' + alen + ']'] = b[alen]
            alen += 1
          }
          // 比较现有的部分
          for (let i = 0; i < Math.min(a.length, b.length); i++) {
            for (const key of Object.keys(a[i]).concat(Object.keys(b[i]))) {
              if (Array.isArray(b[i][key])) {
                if (!Array.isArray(a[i][key])) {
                  data[path + '[' + i + '].' + key] = b[i][key]
                } else {
                  diff(a[i][key], b[i][key], path + '[' + i + '].' + key)
                }
              } else {
                if (typeof b[i][key] !== 'object') {
                  if (a[i][key] !== b[i][key]) {
                    data[path + '[' + i + ']'] = b[i]
                  }
                } else {
                  if (a[i][key] === undefined || b[i][key] === undefined) {
                    data[path + '[' + i + '].' + key] = b[i][key]
                  } else {
                    for (const subKey of Object.keys(a[i][key]).concat(Object.keys(b[i][key]))) {
                      if (a[i][key][subKey] !== b[i][key][subKey]) {
                        data[path + '[' + i + '].' + key + '.' + subKey] = b[i][key][subKey]
                      }
                    }
                  }
                }
              }
            }
          }
        }
        diff(this.data.nodes, nodes, 'nodes')
        this.setData(data)
      }
    }, // 子节点列表
    opts: Array // 设置 [是否开启懒加载, 加载中占位图, 错误占位图, 是否使用长按菜单]
  },
  options: {
    addGlobalClass: true
  },
  // #ifndef MP-TOUTIAO
  attached () {
    // #ifndef MP-ALIPAY
    this.triggerEvent('add', this, {
      bubbles: true,
      composed: true
    })
    // #endif
    // #ifdef MP-ALIPAY
    this.props.onAdd(this)
    // #endif
  },
  // #endif
  methods: {
    noop () { },
    /**
     * @description 获取标签
     * @param {String} path 路径
     */
    getNode (path) {
      try {
        const nums = path.split('_')
        let node = this.properties.childs[nums[0]]
        for (let i = 1; i < nums.length; i++) {
          node = node.children[nums[i]]
        }
        return node
      } catch {
        return {
          text: '',
          attrs: {},
          children: []
        }
      }
    },
    /**
     * @description 播放视频事件
     * @param {Event} e
     */
    play (e) {
      const i = e.target.dataset.i
      const node = this.getNode(i)
      this.root.triggerEvent('play', {
        source: node.name,
        attrs: {
          ...node.attrs,
          src: node.src[this.data.ctrl[i] || 0]
        }
      })
      if (this.root.properties.pauseVideo) {
        let flag = false
        const id = e.target.id
        for (let i = this.root._videos.length; i--;) {
          if (this.root._videos[i].id === id) {
            flag = true
          } else {
            this.root._videos[i].pause() // 自动暂停其他视频
          }
        }
        // 将自己加入列表
        if (!flag) {
          const ctx = wx.createVideoContext(id
            // #ifndef MP-BAIDU
            , this
            // #endif
          )
          ctx.id = id
          if (this.root.playbackRate) {
            ctx.playbackRate(this.root.playbackRate)
          }
          this.root._videos.push(ctx)
        }
      }
    },

    /**
     * @description 图片点击事件
     * @param {Event} e
     */
    imgTap (e) {
      const node = this.getNode(e.target.dataset.i)
      // 父级中有链接
      if (node.a) return this.linkTap(node.a)
      if (node.attrs.ignore) return
      this.root.triggerEvent('imgtap', node.attrs)
      if (this.root.properties.previewImg) {
        const current =
          // #ifndef MP-ALIPAY
          this.root.imgList[node.i]
        // #endif
        // #ifdef MP-ALIPAY
        node.i // eslint-disable-line
        // #endif
        // 自动预览图片
        wx.previewImage({
          // #ifdef MP-WEIXIN
          showmenu: this.root.properties.showImgMenu,
          // #endif
          // #ifdef MP-ALIPAY
          enablesavephoto: this.root.properties.showImgMenu,
          enableShowPhotoDownload: this.root.properties.showImgMenu,
          // #endif
          current,
          urls: this.root.imgList
        })
      }
    },

    /**
     * @description 图片加载完成事件
     * @param {Event} e
     */
    imgLoad (e) {
      const i = e.target.dataset.i
      const node = this.getNode(i)
      let val
      if (!node.w) {
        val = e.detail.width
      } else if ((this.properties.opts[1] && !this.data.ctrl[i]) || this.data.ctrl[i] === -1) {
        // 加载完毕，取消加载中占位图
        val = 1
      }
      if (val
        // #ifdef MP-TOUTIAO
        && val !== this.data.ctrl[i] // eslint-disable-line
        // #endif
      ) {
        this.setData({
          ['ctrl.' + i]: val
        })
      }
      this.checkReady()
    },

    /**
     * @description 检查是否所有图片加载完毕
     */
    checkReady () {
      if (!this.root.properties.lazyLoad) {
        this.root.imgList._unloadimgs -= 1
        if (!this.root.imgList._unloadimgs) {
          setTimeout(() => {
            this.root.getRect().then(rect => {
              this.root.triggerEvent('ready', rect)
            }).catch(() => {
              this.root.triggerEvent('ready', {})
            })
          }, 350)
        }
      }
    },

    /**
     * @description 链接点击事件
     * @param {Event} e
     */
    linkTap (e) {
      const node = e.currentTarget ? this.getNode(e.currentTarget.dataset.i) : {}
      const attrs = node.attrs || e
      const href = attrs.href
      this.root.triggerEvent('linktap', Object.assign({
        innerText: this.root.getText(node.children || []) // 链接内的文本内容
      }, attrs))
      if (href) {
        if (href[0] === '#') {
          // 跳转锚点
          this.root.navigateTo(href.substring(1)).catch(() => { })
        } else if (href.split('?')[0].includes('://')) {
          // 复制外部链接
          if (this.root.properties.copyLink) {
            wx.setClipboardData({
              data: href,
              success: () =>
                wx.showToast({
                  title: '链接已复制'
                })
            })
          }
        } else {
          // 跳转页面
          wx.navigateTo({
            url: href,
            fail () {
              wx.switchTab({
                url: href,
                fail () { }
              })
            }
          })
        }
      }
    },

    /**
     * @description 错误事件
     * @param {Event} e
     */
    mediaError (e) {
      const i = e.target.dataset.i
      const node = this.getNode(i)
      if (node.name === 'video' || node.name === 'audio') {
        // 加载其他源
        let index = (this.data.ctrl[i] || 0) + 1
        if (index > node.src.length) {
          index = 0
        }
        if (index < node.src.length) {
          return this.setData({
            ['ctrl.' + i]: index
          })
        }
      } else if (node.name === 'img') {
        // 显示错误占位图
        if (this.properties.opts[2]) {
          this.setData({
            ['ctrl.' + i]: -1
          })
        }
        this.checkReady()
      }
      if (this.root) {
        this.root.triggerEvent('error', {
          source: node.name,
          attrs: node.attrs,
          errMsg: e.detail.errMsg
        })
      }
    }
  }
})
