text: const fs = require('fs')
  const path = require('path')
  const crypto = require('crypto')
  const fetch = require('node-fetch')
  const { ffmpeg } = require('./converter')
  const { spawn } = require('child_process')
  const uploadFile = require('./uploadFile')
  const { fromBuffer } = require('file-type')
  const uploadImage = require('./uploadImage')
  
  const tmp = path.join(__dirname, '../tmp')
  /**
   * Image to Sticker
   * @param {Buffer} img Image Buffer
   * @param {String} url Image URL
   */
  function sticker2(img, url) {
    return new Promise(async (resolve, reject) => {
      try {
        if (url) {
          let res = await fetch(url)
          if (res.status !== 200) throw await res.text()
          img = await res.buffer()
        }
        let inp = path.join(tmp, +new Date + '.jpeg')
        await fs.promises.writeFile(inp, img)
        let ff = spawn('ffmpeg', [
          '-y',
          '-i', inp,
          '-vf', 'scale=512:512:flags=lanczos:force_original_aspect_ratio=decrease,format=rgba,pad=512:512:(ow-iw)/2:(oh-ih)/2:color=#00000000,setsar=1',
          '-f', 'png',
          '-'
        ])
        ff.on('error', reject)
        ff.on('close', async () => {
          await fs.promises.unlink(inp)
        })
        let bufs = []
        const [_spawnprocess, ..._spawnargs] = [...(module.exports.support.gm ? ['gm'] : module.exports.magick ? ['magick'] : []), 'convert', 'png:-', 'webp:-']
        let im = spawn(_spawnprocess, _spawnargs)
        im.on('error', e => conn.reply(m.chat, util.format(e), m))
        im.stdout.on('data', chunk => bufs.push(chunk))
        ff.stdout.pipe(im.stdin)
        im.on('exit', () => {
          resolve(Buffer.concat(bufs))
        })
      } catch (e) {
        reject(e)
      }
    })
  }
  
  async function canvas(code, type = 'png', quality = 0.92) {
    let res = await fetch('https://nurutomo.herokuapp.com/api/canvas?' + queryURL({
      type,
      quality
    }), {
      method: 'POST',
      headers: {
        'Content-Type': 'text/plain',
        'Content-Length': code.length
      },
      body: code
    })
    let image = await res.buffer()
    return image
  }
  
  function queryURL(queries) {
    return new URLSearchParams(Object.entries(queries))
  }
  
  /**
   * Image to Sticker
   * @param {Buffer} img Image Buffer
   * @param {String} url Image URL
   */
  async function sticker1(img, url) {
    url = url ? url : await uploadImage(img)
    let {
      mime
    } = url ? { mime: 'image/jpeg' } : await fromBuffer(img)
    let sc = `let im = await loadImg('data:${mime};base64,'+(await window.loadToDataURI('${url}')))
  c.width = c.height = 512
  let max = Math.max(im.width, im.height)
  let w = 512 * im.width / max
  let h = 512 * im.height / max
  ctx.drawImage(im, 256 - w / 2, 256 - h / 2, w, h)
  `
    return await canvas(sc, 'webp')
  }
  
  /**
   * Image/Video to Sticker
   * @param {Buffer} img Image/Video Buffer
   * @param {String} url Image/Video URL
   * @param {String} packname EXIF Packname
   * @param {String} author EXIF Author
   */
  async function sticker3(img, url, packname, author) {
    url = url ? url : await uploadFile(img)
    let res = await fetch('https://api.xteam.xyz/sticker/wm?' + new URLSearchParams(Object.entries({
      url,
      packname,
      author
    })))
    return await res.buffer()
  }
  
  /**
   * Image to Sticker
   * @param {Buffer} img Image/Video Buffer
   * @param {String} url Image/Video URL
   */
  async function sticker4(img, url) {
    if (url) {
      let res = await fetch(url)
      if (res.status !== 200) throw await res.text()
      img = await res.buffer()
    }
    return await ffmpeg(img, [
      '-vf', 'scale=512:512:flags=lanczos:force_original_aspect_ratio=decrease,format=rgba,pad=512:512:(ow-iw)/2:(oh-ih)/2:color=#00000000,setsar=1'
    ], 'jpeg', 'webp')
  }
  
  
  async function sticker5(img, url, packname, author, categories = ['']) {
    const WSF = require('wa-sticker-formatter')
    const stickerMetadata = {
      type: 'full',
      pack: packname,
      author,
      categories,
    }
    return await new WSF.Sticker(img ? img : url, stickerMetadata).build()
  }
  
  
  /**
   * Add WhatsApp JSON Exif Metadata
   * Taken from https://github.com/pedroslopez/whatsapp-web.js/pull/527/files
   * @param {Buffer} webpSticker 
   * @param {String} packname 
   * @param {String} author 
   * @param {String} categories 
   * @param {Object} extra 
   * @returns 
   */
  async function addExif(webpSticker, packname, author, categories = [''], extra = {}) {
    const webp = require('node-webpmux') // Optional Feature
    const img = new webp.Image();
    const stickerPackId = crypto.randomBytes(32).toString('hex');
    const json = { 'sticker-pack-id': stickerPackId, 'sticker-pack-name': packname, 'sticker-pack-publisher': author, 'emojis': categories, ...extra };
    let exifAttr = Buffer.from([0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x41, 0x57, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00]);
    let jsonBuffer = Buffer.from(JSON.stringify(json), 'utf8');
    let exif = Buffer.concat([exifAttr, jsonBuffer]);
    exif.writeUIntLE(jsonBuffer.length, 14, 4);
    await img.load(webpSticker)
    img.exif = exif
    return await img.save(null)
  }
  
  module.exports = {
    /**
     * Image/Video to Sticker
     * @param {Buffer} img Image/Video Buffer
     * @param {String} url Image/Video URL
     * @param {...String} 
     */
    async sticker(img, url, ...args) {
      let lastError
      for (let func of [
        sticker3, // sticker5,
        this.support.ffmpeg && this.support.ffmpegWebp && sticker4,
        this.support.ffmpeg && (this.support.convert || this.support.magick || this.support.gm) && sticker2,
        sticker1
      ].filter(f => f)) {
        try {
          let stiker = await func(img, url, ...args)
          if (stiker.includes('RIFF')) {
            try {
              return await addExif(stiker, ...args)
            } catch (e) {
              return stiker
            }
          }
          throw stiker.toString()
        } catch (err) {
          lastError = err
        }
      }
      return lastError
    },
    sticker1,
    sticker2,
    sticker3,
    sticker4,
    sticker5,
    addExif,
    support: {
      ffmpeg: true,
      ffprobe: true,
      ffmpegWebp: true,
      convert: true,
      magick: false,
      gm: false,
      find: false
    }
  }
  