import request from 'request'
import cheerio from 'cheerio'
import { merge } from 'lodash'
import getImageSize from '../services/GetImageSize'

const httpget = url => new Promise((resolve, reject) =>
  request.get(url, {gzip: true}, (err, res, body) =>
    err ? reject(err) : resolve([res, body])))

const parse = body => {
  const $ = cheerio.load(body)
  const metaContent = name => $(`meta[property="${name}"]`).attr('content')
  return {
    title: metaContent('og:title') || $('title').text(),
    description: metaContent('og:description'),
    image_url: metaContent('og:image')
  }
}

const LinkPreview = bookshelf.Model.extend({
  tableName: 'link_previews'

}, {
  parse,

  queue: url => {
    return LinkPreview.forge({url, created_at: new Date()}).save()
    .then(({ id }) => Queue.classMethod('LinkPreview', 'populate', {id}, 0))
    .catch(err => {
      if (err.message && !err.message.includes('duplicate key value')) {
        throw err
      }
    })
  },

  populate: ({ id }) => {
    return LinkPreview.find(id).then(preview =>
      httpget(preview.get('url'))
      .then(([ res, body ]) => {
        const attrs = merge(parse(body), {updated_at: new Date(), done: true})

        return (attrs.image_url
          ? getImageSize(attrs.image_url).catch(err => null) // eslint-disable-line handle-callback-err
          : Promise.resolve())
        .then(size => {
          if (!size) return
          attrs.image_width = size.width
          attrs.image_height = size.height
        })
        .then(() => preview.save(attrs, {patch: true}))
      }))
  },

  find: (idOrUrl, opts) => {
    const attr = isNaN(Number(idOrUrl)) ? 'url' : 'id'
    return LinkPreview.where(attr, idOrUrl).fetch(opts)
  }
})

module.exports = LinkPreview

@@ -993,24 +993,91 @@
  id %7D) =%3E %7B%0A
+    const doneAttrs = () =%3E (%7Bupdated_at: new Date(), done: true%7D)%0A
     return L
@@ -1157,33 +1157,175 @@
    .
-then((%5B res, body %5D) =%3E %7B
+catch(err =%3E preview.save(doneAttrs()) && null) // eslint-disable-line handle-callback-err%0A      .then(resp =%3E %7B%0A        if (!resp) return%0A        const body = resp%5B1%5D
 %0A   
@@ -1366,44 +1366,19 @@
 y), 
-%7Bupdated_at: new Date(), done: true%7D
+doneAttrs()
 )%0A%0A 

handle http errors in LinkPreview.populate