// uniapp people side tools
import './ican-H5Api.js' // 对齐H5Api: https://ext.dcloud.net.cn/plugin?id=415 // 注意要取消默认自带的 showToast https://uniapp.dcloud.io/api/system/clipboard?id=%e6%b3%a8%e6%84%8f
export default {
  // 用直观的色彩,代替 uview 的命名方式:
  RED: 'error',
  GREEN: 'success',
  BLUE: 'primary',
  YELLOW: 'warning',
  GREY: 'info',
  BLACK_TOAST: 'default',
  WHITE_BUTTON: 'default',
  // [todo] 能否把这些默认值放到 export 以外?
  RESPONSIVE_TABBAR_AUTOHIDE_WIDTH_THRESHOLD_DEFAULT: 0,
  BACKEND_DEFAULT: 'SERVER', // 服务器 SERVER 或云服务 UNICLOUD
  thisPage() {
    return this.constructor.name==='VueComponent' ? this // 对于组件内定义的 i18nText,要使用 this 来获得组建内的 i18nText,而不是 getCurrentPages[...] 去访问全局页面的 i18nText。 
      : ( getCurrentPages()[getCurrentPages().length - 1] // [20220401] 发现在 topWindow 里, getCurrentPages 是 undefined。
        || {} ) // 用 {} 做备份是为了在 App.vue 中使用时,getCurrentPages() 有可能获取不到。
  },
  // 输出命令行提示,可用来取代 console.log/info/warn/error
  cclog(...args) {
    const pageName = this.thisPage()?.route || 'VueApp'
    console.log('%c '+JSON.stringify({time:new Date().toJSON(), page:pageName}), 'color:blue', ...args)
  },
  ccinfo(...args) {
    const pageName = this.thisPage()?.route || 'VueApp'
    console.info('%c '+JSON.stringify({time:new Date().toJSON(), page:pageName}), 'color:green', ...args)
  },
  ccwarn(...args) {
    const pageName = this.thisPage().route || 'VueApp'
    console.warn('%c '+JSON.stringify({time:new Date().toJSON(), page:pageName}), 'color:orange', ...args)
  },
  ccerr(...args) {
    const pageName = this.thisPage()?.route || 'VueApp'
    console.error('%c '+JSON.stringify({time:new Date().toJSON(), page:pageName}), 'color:red', ...args)
  },
  ccdebug(...args) {
    if (process.env.NODE_ENV === 'development') {
      const pageName = this.thisPage()?.route || 'VueApp'
      console.debug('%c '+JSON.stringify({time:new Date().toJSON(), page:pageName}), 'color:cyan', ...args)
    }
  },
  localizeText(i18nText) {
    i18nText = i18nText?.constructor?.name==='VueComponent' ? this.i18nText // 如果挂载到具体页面的 computed { lote: wo.localizeText } 那么 this 就是当前页面,直接取用 this.i18nText 即可。
      : ( i18nText // 如果传入i18n参数 ({zhCN:'...', enUS:'...'})
        || this.thisPage()?.i18nText)  // 如果不是挂载到 Vue.prototype 而是 挂载到 wo 下调用,那么 this.i18nText 就报错了。因此通过 thisPage().i18nText 访问。
    const mylang = getApp().$store.state.i18n.mylang // this.thisPage() 有可能为空(例如在 topWindow 里,或者在 App.vue 里),所以用 getApp().$store 更安全
    return i18nText?.[mylang] || (typeof i18nText === 'string' ? i18nText : '') // 必须检测是否string,如果直接返回 i18nText 可能返回{}等,导致依赖于返回空值的前端出错
  },
  localeText() { // 专供绑定到 computed { lote: wo.localeText } 使用,这时 this 就是当前页面。
    return this.i18nText?.[getApp().$store.state.i18n.mylang] || {}
  },
  setBarTitles ({ windowTitle, pageTitle, 
    pagesJson=this.pagesJson || wo?.pagesJson } = {}
  ) {
    const mylang = getApp().$store.state.i18n.mylang
    const pageNow = getCurrentPages()[getCurrentPages().length - 1]
    // #ifdef H5
    document.title = windowTitle || pagesJson?.appInfo?.i18nText?.[mylang] // 必须放在 setNavigationBarTitle 之后,否则会被其覆盖掉。
    // #endif
    uni.setNavigationBarTitle({
      title:
        pageTitle ||
        pageNow?.i18nText?.[mylang]?.tPageTitle || // 页面.vue 的 i18nText 对象
        pageNow?.i18nPageTitle?.[mylang] || // 页面.vue 的 i18nPageTitle 变量
        pagesJson?.pages?.find((page) => page.path === pageNow.route)?.i18nPageTitle?.[mylang], // pages.json 的页面配置里
    })
    // 必须要在有 tab 的页面里 setTabBarItem 才有效果
    //const midIndex = parseInt(pagesJson?.tabBar?.list?.length/2) // 如果存在midButton,实际上tabBar.list.length必须为偶数。不过为了心安,再parseInt一下。
    pagesJson?.tabBar?.list?.forEach((tab, tabIndex) => {
      if (tab.i18nText && tab.i18nText[mylang]) {
        uni.setTabBarItem({
          // #ifdef H5
          index: tabIndex, // + ((pagesJson?.tabBar?.midButton?.iconPath && tabIndex >= midIndex)?1:0), // H5 里,如果使用了 midButton,tabBarItem的index出现错位,需hack调整。推测,在H5里 midButton 作为一个普通tab被插入到 tabBar 里,导致 tabBar 的 index 和 pagesJson.tabBar.list 的 index 错位了。[20211031] 注意到,从 HBuilderX 3.2.12.20211029 起,在 H5 里也没有错位了。 
          // #endif
          // #ifndef H5
          index: tabIndex,
          // #endif
          text: tab.i18nText[mylang],
        })
      }
    })
    //  uni.showTabBar({})
      
    // #ifdef H5
    if (uni.getSystemInfoSync().model==='PC') {
      const envar = this.envar || wo?.envar || {}
      if (envar.Responsive_Tabbar==='AUTOHIDE') {
        if (window.screen.width > (envar.Responsive_Tabbar_Autohide_Width_Threshold || this.RESPONSIVE_TABBAR_AUTOHIDE_WIDTH_THRESHOLD_DEFAULT)) {
          uni.hideTabBar()
        }
        uni.onWindowResize(({size})=>{
          if (size.windowWidth > (envar.Responsive_Tabbar_Autohide_Width_Threshold || this.RESPONSIVE_TABBAR_AUTOHIDE_WIDTH_THRESHOLD_DEFAULT)) {
            uni.hideTabBar()
          }else{
            uni.showTabBar()
          }
        })
      }else if (envar.Responsive_Tabbar==='ALWAYSHIDE') {
        uni.hideTabBar()
      }
    }
    // #endif  
  },
  makeServerUrl(route = '') {
    const envar = this.envar || wo?.envar || {}
    if (typeof route !== 'string') route = '' // 防止 route 为 null, undefined 等由于后台数据库默认值而造成的异常。
    route = route.replace('\\', '/')
    if (/^https?:\/\//.test(route)) {
      return route
    }
    let protocol, hostname, port
    if (process.env.NODE_ENV === 'production') {
      protocol = envar.Base_Protocol || 'https'
      hostname = envar.Base_Hostname
      port = envar.Base_Port
    }else{
      protocol = envar.Base_Protocol_Dev || 'http'
      hostname = envar.Base_Hostname_Dev
        // #ifdef H5
        || window.location.hostname
        // #endif
      port = envar.Base_Port_Dev || envar.Base_Port
        // #ifdef H5
        || window.location.port.replace(':','')
        // #endif
    }
    return `${protocol}://${hostname}:${port}/${route.replace(/^\//, '')}`
  },
  makeBgUrl(path) {
    if (path) {
      return `url(${this.makeServerUrl(path)})`
    }
    return ''
  },
  relaunchForAll ({envar=this.envar || wo?.envar || {}} = {}) {
    uni.reLaunch({ url: envar?.Start_Page_For_All })
  },
  relaunchForOnline ({envar=this.envar || wo?.envar || {}} = {}) {
    process.env.NODE_ENV === 'production' && 
    wo.ss.User.onlineUser.uuid && 
    uni.reLaunch({ url: envar?.Start_Page_For_Online })
  },
  relaunchForOffline ({envar=this.envar || wo?.envar || {}} ={}) {
    process.env.NODE_ENV === 'production' && 
    ! wo.ss.User.onlineUser.uuid && 
    uni.reLaunch({ url: envar?.Start_Page_For_Offline })
  },
  /** 统一 uni.request 和 uniCloud.callFunction 的调用方法,提供统一、透明的后台调用
   * 返回值:{ _state, 成功结果或错误结果 },其中 _state 除了后台返回的,还可以是
   * - CLIENT_BACKEND_BROKEN: 前端发现后台断线
   * - CLIENT_BACKEND_TIMEOUT: 前端发现后台超时
   * - CLINET_BACKEND_EXCEPTION: 前端发现后台异常
  **/
  async callBackend({ 
    backend = this.envar?.Backend_Default || wo?.envar?.Backend_Default || this.BACKEND_DEFAULT, 
    httpMethod = 'POST', 
    apiVersion = 'api', apiWho, apiTodo, apiWhat = {} 
  }) {
    const thisRoute = this.thisPage()?.route || 'VueApp' // 立刻保存 this.thisPage().route,因为在调用后台后,可能已切换到了其他页面。
    const startTime = new Date().toJSON()
    let result = {}
    if (backend === 'UNICLOUD') {
      let { /* success, header, requestedId, */ result: resultCloud = {} } = await uniCloud
        .callFunction({
          name: apiWho,
          data: {
            apiTodo,
            apiWhat,
            _passtoken: uni.getStorageSync('_passtoken'),
            // uniIdToken // uniCloud自动getStorageSync('uni_id_token')并传递为 uniIdToken;也可自行组装传入 uniIdToken
          },
        })
        .catch((error) => { // {errMsg, stack} = error
          if (/request:fail/.test(error.errMsg)) { 
            // 后台云服务无法连接
            result = { _state: 'CLIENT_BACKEND_BROKEN', error }
          } else {
            // 后台云服务返回异常
            result = { _state: 'CLIENT_BACKEND_EXCEPTION', error }
          }
        })
      result = resultCloud
    } else {
      if (httpMethod === 'GET') {
        // 如果不是 POST 方法,要额外把参数JSON化
        for (let key in apiWhat) {
          apiWhat[key] = JSON.stringify(apiWhat[key])
        }
      }
      let [error, { statusCode, header, errMsg, data: resultServer = {} } = {}] = await uni.request({
        method: httpMethod,
        url: this.makeServerUrl(`${apiVersion}/${apiWho}/${apiTodo}`),
        header: { _passtoken: uni.getStorageSync('_passtoken') },
        data: apiWhat,
      })
      if (error) {
        if (error.errMsg === 'request:fail') {
          // 后台服务器无法连接
          result = { _state: 'CLIENT_BACKEND_BROKEN', error }
        } else if (error.errMsg === 'request:fail timeout') {
          // 后台服务器超时
          result = { _state: 'CLIENT_BACKEND_TIMEOUT', error }
        } else {
          // 后台服务器返回异常
          result = { _state: 'CLIENT_BACKEND_EXCEPTION', error }
        }
      } else {
        result = resultServer
      }
    }
    // 注意1,resultServer 和 resultCloud 推荐遵循同样的格式 { _state, error | data },这样方便前端做统一判断。
    // 注意2,虽然预设了 resultServer 和 resultCloud = {},但如果后台返回了 null,那么 resultServer/resultCloud 也是 null。
    if (process.env.NODE_ENV === 'development') {
      console.log(
        '%c '+JSON.stringify({startTime:startTime, page:thisRoute}) +
        ' %c '+ JSON.stringify({ backend, apiWho, apiTodo, apiWhat }) +
        ' %c '+ JSON.stringify(result) +
        ' %c '+ JSON.stringify({endTime:new Date().toJSON()}), 
        'color:blue', 'background:skyblue', 'background:magenta', 'color:magenta') // 不知为何,直接用 result 会输出一个奇怪的对象,要主动添加 JSON.stringify 才按照期望输出。
    }
    return result
  },
  async pickupFile2Server({
    mediaType = 'image',
    count = 1,
    sizeType = ['original', 'compressed'],
    sourceType = ['album', 'camera'],
    url = 'api/FileTransfer/receiveFile', // 默认后台用这个接口来接受文件
    header = {},
    formData = {},
    name = 'file',
  } = {}) {
    // 有的管理后台不需要登录就允许上传,例如 cmctoy。因此不要在这里依赖登录状态。
    // if (uni.getStorageSync('_passtoken')) {
    //   header._passtoken = uni.getStorageSync('_passtoken')
    // } else {
    //   return [{ _ERROR: 'USER_OFFLINE', errMsg: 'offline user cannot upload files' }, null]
    // }
    let filePath
    if (mediaType === 'image') {
      let [errorChoose, { tempFilePaths, tempFiles } = {}] = await uni.chooseImage({ count, sizeType, sourceType })
      filePath = tempFilePaths[0]
    } else if (mediaType === 'video') {
      let [errorChoose, { tempFilePath }] = await uni.chooseVideo({ sourceType })
      filePath = tempFilePath
    } else {
      return { _state: 'UNKNOWN_MEDIATYPE' }
    }
    if (filePath) {
      for (let key in formData) {
        // multer 不会自动处理 JSON 数据,必须前后端配合处理
        formData[key] = JSON.stringify(formData[key])
      }
      header._passtoken = uni.getStorageSync('_passtoken')
      uni.showLoading()
      let [errorUpload, { data, statusCode } = {}] = await uni.uploadFile({ url: this.makeServerUrl(url), filePath, name, header, formData })
      // 后台 Multer 处理 req.file = { destination, filename, originalname, path, mimetype, size }, 
      // url 所在方法进一步处理后,通过 uploadFile 存在 data 里返回结果
      uni.hideLoading()
      if (typeof(data)==='string') { // 不知为何,uni.uploadFile返回的 data 是字符串而不是对象
        try{ 
          data = JSON.parse(data)
        }catch(exp){
          return { _state: 'CLIENT_FAIL_RESPONSE_JSON_MALFORMED'}
        }
      }
      if (data?._state==='SUCCESS' && data?.path) {
        return { _state: 'SUCCESS', fileUrl: this.makeServerUrl(data.path), filePath: data.path, ...data }
      }else {
        return { _state: 'CLIENT_FAIL_UPLOAD_FILE', errorUpload }
      }
    }else {
      return { _state: 'CLIENT_FAIL_CHOOSE_FILE' }
    }
  },
  async pickupFile2Cloud({ mediaType = 'image', count = 1, sizeType = ['original', 'compressed'], sourceType = ['album', 'camera'], maxDuration } = {}) {
    // 有的管理后台不需要登录就允许上传,例如 cmctoy。因此不要在这里依赖登录状态。
    // if (!uni.getStorageSync('_passtoken')) {
    //   return { _state: 'USER_OFFLINE', errMsg: 'offline user cannot upload files' }
    // }
    let filePath,
      cloudPath,
      systemInfo = this.getSystemInfo()
    if (mediaType === 'image') {
      let [errorChoose, { tempFilePaths, tempFiles } = {}] = await uni.chooseImage({ count, sizeType, sourceType })
      //      uni.showModal({ title: 'tempFilePaths[0]=' + tempFilePaths[0] })
      filePath = tempFilePaths[0] // 在 H5 上并不是文件路径名,而是类似 "blob:http://localhost:8080/f0d3e54d-0694-4803-8097-641d76a10b0d“。
      // #ifndef H5
      // let [errorGetImageInfo, { path, width, height, orientation, type }] = await uni.getImageInfo({ src: filePath })
      // cloudPath = path // 完整路径,包含后缀名。形如 file:///var/mobile/Containers/Data/Application/55A76332-44F5-4D5F-A9F6-3F857D584883/Documents/Pandora/apps/D064A425A8BEC13F9D8F741B98B37BC5/doc/uniapp_temp_1598593902955/compressed/1598593925815.png
      cloudPath = `APP_${systemInfo.platform}__${filePath}` // 在 iOS 上是 "_doc/uniapp_temp_1598593902955/compressed/1598593925815.png", 有时还包含从 file:/// 开始的完整路径名
      // #endif
      // #ifdef H5
      cloudPath = `H5_${systemInfo.platform}_${systemInfo.browser}__${tempFiles[0].name}` // name is available in H5 only. 只包含文件名和后缀名,不包含路径。
      // #endif
    } else if (mediaType === 'video') {
      let [errorChoose, { tempFilePath, tempFile, duration, size, width, height, name }] = await uni.chooseVideo({ sourceType, maxDuration })
      //      uni.showModal({ title: 'tempFilePath=' + tempFilePath })
      filePath = tempFilePath // 在 iOS 上形如 "file:///var/mobile/Containers/Data/Application/55A76332-44F5-4D5F-A9F6-3F857D584883/Documents/Pandora/apps/26B43CD2F587D37FC6799108434A6F84/doc/uniapp_temp_1598596171580/gallery/IMG_3082.MOV"
      // #ifndef H5
      cloudPath = `APP_${systemInfo.platform}_dur${duration}__${filePath}`
      // #endif
      // #ifdef H5
      cloudPath = `H5_${systemInfo.platform}_${systemInfo.browser}_dur${duration}__${name}` // tempFile and name are H5 only
      // #endif
      // iOS 上测试,filePath 为 *.MOV,而阿里云只允许 *.mp4, 所以添加 .mp4 后缀。参见 https://uniapp.dcloud.net.cn/uniCloud/storage?id=clouduploadfile
      // 20200915测试,阿里云支持上传 *.mov 了。
      if (!/\.(mp4|mov)$/i.test(cloudPath)) cloudPath = cloudPath + '.mp4'
    } else {
      return { _state: 'CLIENT_FAIL_UNKNOWN_MEDIA_TYPE' }
    }
    if (process.env.NODE_ENV === 'development') {
      cloudPath = 'dev_' + cloudPath
    }
    if (filePath) {
      uni.showLoading()
      const { fileID, requestId } = await uniCloud.uploadFile({
        filePath: filePath,
        cloudPath: cloudPath, // 关键是要具有文件格式后缀名,这样可以保持阿里云下载链接也用这个后缀名。
        fileType: mediaType, // = image, video, audio
        onUploadProgress: function (progressEvent) {
          var percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
        },
      })
      uni.hideLoading()
      if (fileID) {
        return { _state: 'SUCCESS', fileUrl: fileID, requestId }
      }
    }
    return { _state: 'CLIENT_FAIL_CHOOSE_FILE' }
  },
  async pickupFile({ 
    backend = this.envar?.Backend_Default || wo?.envar?.Backend_Default || this.BACKEND_DEFAULT,
    mediaType = 'image', count = 1, sizeType = ['original', 'compressed'], sourceType = ['album', 'camera'], maxDuration,
    url, header = {}, formData = {}, name = 'file',
  }) {
    if (backend==='UNICLOUD'){
      const resultCloud = await this.pickupFile2Cloud({mediaType, count, sizeType, sourceType, maxDuration })
      return resultCloud
    }else if (backend==='SERVER'){
      const resultServer = await this.pickupFile2Server({mediaType, count, sizeType, sourceType, maxDuration, url, header, formData, name})
      return resultServer
    }else {
      return { _state: 'CLEINT_FAIL_UNKNOWN_BACKEND_TYPE', backend }
    }
  },
  openUrl(url) {
    // #ifdef APP-PLUS
    plus.runtime.openURL(url)
    // #endif
    // #ifdef H5
    window.open(url, '_blank')
    // #endif
  },
  getSystemInfo() {
    let systemInfo = uni.getSystemInfoSync()
    // model=PC|iPhone|iPad|Nexus 6|...,
    // platform=ios|android|mac|windows|linux|other,
    // system=iOS 11.0|Android 4.0|Other 0|... 等等
    // #ifdef H5
    systemInfo.environment = 'h5'
    let userAgent = window.navigator.userAgent.toLowerCase()
    systemInfo.browser =
      /msie/.test(userAgent) && !/opera/.test(userAgent)
        ? 'msie'
        : /opera/.test(userAgent)
        ? 'opera'
        : /version.*safari/.test(userAgent)
        ? 'safari'
        : /chrome/.test(userAgent)
        ? 'chrome'
        : /gecko/.test(userAgent) && !/webkit/.test(userAgent)
        ? 'firefox'
        : /micromessenger/.test(userAgent)
        ? 'wechat'
        : 'unknown'
    // #endif
    // #ifdef APP-PLUS || APP-PLUS-NVUE
    systemInfo.environment = 'app'
    // #endif
    // #ifdef MP
    systemInfo.environment = 'mp'
    // 细分成 WEIXIN, ...
    // #endif
    return systemInfo
  },
  /*
   * uni.showToast({ 
     icon=success (by default)/loading/none, 
     position(app only):center|top|bottom, 
     success, fail, complete // 函数调用后立刻发生,不是在toast之后
    })
   * ucToast.show({ 
     type=info (by default)/success/error/warning|loading, 
     position:top/bottom 
    })
   * u-toast.show({ 
     type=default (by default)/primary/success/error/warning/info, 
     position:center/top/bottom, 
     callback // 发生在 toast 之后
    })
   */
  showToast({ tool, type, image, title, duration = 2000, ...rest }) {
    const pageNow = this.thisPage()
    if (tool === 'uni' || ! pageNow?.$refs?.toast) {
      // #ifdef APP-PLUS
      uni.showToast({ icon: 'none', title, duration, ...rest })
      // #endif
      // #ifdef H5
      uni.showToast({ icon: 'none', image, title, duration, ...rest })
      // #endif
    } else {
      // 根据 html 中不同的组件  或  而不同。
      pageNow.$refs.toast.show({ type, title, duration, ...rest })
    }
  },
  formatMoney(value, precision=2) {
    return Number(value || 0).toFixed(precision) // Number(undefined)===NaN
  },
  formatPercent(value, precision=2) {
    return Number(value * 100 || 0).toFixed(precision)
  },
  formatDate(date, format) {
    if (!(date instanceof Date)) {
      if (typeof date === 'string' && /^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d$/.test(date)) {
        // 这是从 typeorm 数据库得到的Date类型的值
        date = date.replace(/-/g, '/') // safari 不支持 yyyy-mm-dd,必须改成 yyyy/mm/dd
      }
      date = new Date(date)
    }
    if (!date.toJSON()) {
      date = new Date()
    }
    format = format && typeof format === 'string' ? format : 'yyyy-mm-dd HH:MM:SS'
    let o = {
      'm+': date.getMonth() + 1, //月份
      'q+': Math.floor((date.getMonth() + 3) / 3), //季度
      'd+': date.getDate(), //日
      'H+': date.getHours(), //小时
      'M+': date.getMinutes(), //分
      'S+': date.getSeconds(), //秒
      s: date.getMilliseconds(), //毫秒
    }
    if (/(y+)/.test(format)) format = format.replace(RegExp.$1, `${date.getFullYear()}`.substr(4 - RegExp.$1.length))
    for (var k in o) {
      if (new RegExp(`(${k})`).test(format)) format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : `00${o[k]}`.substr(`${o[k]}`.length))
    }
    return format
  },
  getUserEndLanIp(callback) {
		let recode = {}
		let RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection
		// 如果不存在则使用一个iframe绕过
		if (!RTCPeerConnection) {
			// 因为这里用到了iframe,所以在调用这个方法的script上必须有一个iframe标签
			// 
			let win = iframe.contentWindow
			RTCPeerConnection = win.RTCPeerConnection || win.mozRTCPeerConnection || win.webkitRTCPeerConnection
		}
		//创建实例,生成连接
		let pc = new RTCPeerConnection()
		// 匹配字符串中符合ip地址的字段
		function handleCandidate(candidate) {
			let ip_regexp = /([0-9]{1,3}(\.[0-9]{1,3}){3}|([a-f0-9]{1,4}((:[a-f0-9]{1,4}){7}|:+[a-f0-9]{1,4}){6}))/
			let ip_isMatch = candidate.match(ip_regexp)[1]
			if (!recode[ip_isMatch]) {
				callback(ip_isMatch)
				recode[ip_isMatch] = true
			}
		}
		//监听icecandidate事件
		pc.onicecandidate = (ice) => {
			if (ice.candidate) {
				handleCandidate(ice.candidate.candidate)
			}
		};
		//建立一个伪数据的通道
		pc.createDataChannel('')
		pc.createOffer((res) => {
			pc.setLocalDescription(res)
		}, () => {})
		//延迟,让一切都能完成
		setTimeout(() => {
			let lines = pc.localDescription.sdp.split('\n')
			lines.forEach(item => {
				if (item.indexOf('a=candidate:') === 0) {
					handleCandidate(item)
				}
			})
		}, 1000)
	},
}