{Writer} = require 'nsqjs'
_ = require 'lodash'
errors = require '../errors'
rp = require 'request-promise'
Promise = require 'bluebird'

class NsqWriter
  constructor: (@ip, @port, @debug=false) ->
    @ready = false
    @closed = true
    @queue = []

    @connect()

  console: (msg) ->
    if @debug is on
      console.log msg

  get_nsqd: ->
    rp.get {
      uri: "http://#{@ip}:#{@port}/nodes"
      json: true
    }
    .then (data) ->
      if data.status_code is 200 and data.status_txt is 'OK'
        num = _.random(0, data.data.producers.length-1)
        Promise.resolve data.data.producers[num]
      else
        Promise.reject()

  connect: ->
    @get_nsqd().then (data) =>
      if @closed is off
        @w.close()
      @w = new Writer data.broadcast_address, data.tcp_port
      @w.connect()
      @closed = false

      @w.on Writer.CLOSED, =>
        @console 'nsq writer closed'
        @ready = false
        @closed = true
        @connect()

      @w.on Writer.ERROR, =>
        @console 'nsq writer error'
        @ready = false
        @w.close()

      @w.on Writer.READY, =>
        console.log 'nsq is ready'
        @ready = true
        arr = []
        while @queue.length
          arr.push @queue.pop()
        Promise.map arr, (obj) =>
          @publish obj.topic, obj.data
    .catch (err) =>
      console.log @ip
      console.log @port
      console.log err.stack
      Promise.delay 5000
      .then =>
        @connect()

  write: (topic, data) ->
    new Promise (resolve, reject) =>
      @w.publish topic, data, (err) =>
        if err
          @console 'nsq write fail'
          return reject err
        @console 'nsq write success'
        resolve()

  publish: (topic, data) ->
    if @ready is on
      @write topic, data
      .catch (err) =>
        @queue.push {
          topic: topic
          data: data
        }
    else
      @queue.push {
        topic: topic
        data: data
      }

  close: ->
    @can_close = true
    @w.close()

module.exports = NsqWriter