# Author: VTEX

NodeCache = require 'node-cache'
VTEX = require 'vtex-node-sdk'
request = require 'request'
Q = require 'q'

FIVE_MINUTES = 5 * 60

LicenseManagerClient = VTEX.LicenseManagerClient

class LicenseManagerCall

  # Scoping private methods
  setCache = null
  lmError = null

  constructor: (options) ->
    @options = options
    @cache = new NodeCache(stdTTL: @options.ttl or (FIVE_MINUTES * 6))
    @lmClient = new LicenseManagerClient()

    ########################
    # Private methods      #
    ########################

    setCache = (req, key, value) =>
      @options.logger?.debug 'Setting topbar data in cache'
      @cache.set key, value

    lmError = (topbar, req, res) =>
      @options.logger?.warn 'License Manager responded with message:', topbar.error
      res.statusCode = 302
      res.setHeader 'Location', "/admin/logout" + "?previousUrl=" + req.url
      return res.end()

  ########################
  # Handler              #
  ########################

  handler: (req, res, next) =>
    @options.logger?.debug('LicenseManagerCall middleware')
    return next() if @options.utils.isAdmin(req, @options) is false
    return next() if req.url.indexOf('/admin/logout') isnt -1
    return next() if req.url.indexOf('/admin/login') isnt -1

    # First, we check if LM's response is cached
    verifyCache = (value) ->
      cachedUser = value[req.cookies.VtexIdclientAutCookie]
      try
        cachedUser = JSON.parse(cachedUser)
        topbarJson = JSON.stringify(cachedUser[req.vtex.store])
      catch e
      finally
        if topbarJson?
          return isCached(topbarJson)
        else
          return isntCached()

    #
    # Now we can use distinct strategies if it is
    # cached or not :)
    #

    # Not cached: fetch topbar info, add it to the
    # request context and cache
    isntCached = =>
      success = (response, topbar) ->
        return lmError(topbar, req, res) if topbar.error
        info = {}
        info[req.vtex.store] = topbar
        info = JSON.stringify(info)
        topbarJson = JSON.stringify(topbar)
        req.licenseManagerResponse = topbarJson
        return setCache(req, req.cookies.VtexIdclientAutCookie, info)

      @options.logger?.info 'Calling License Manager for topbar info'

      promise = @lmClient.getTopbarInfo(req.vtex.store, req.cookies.VtexIdclientAutCookie)
      .spread(success)

    # Cached: Adds topbar info to the request context
    isCached = (topbarJson) =>
      deferred = Q.defer()
      @options.logger?.info 'Getting topbar data from cache'
      try
        topbar = JSON.parse(topbarJson)
        req.licenseManagerResponse = topbarJson
        deferred.resolve()
      catch e
        deferred.reject(e)
      return deferred.promise

    #
    # Promise calls
    #

    Q.ninvoke(@cache, 'get', [req.cookies.VtexIdclientAutCookie])
      .then(verifyCache)
      .then(-> next())
      .catch(next)


module.exports = LicenseManagerCall
