# Description:
#   Spin & spun text formatter script
#
# Dependencies:
#   None
#
# Configuration:
#   HUBOT_SPINNER_SECRET_KEY
#   HUBOT_SPINNER_ACCESS_KEY
#
# Commands:
#   spin me <query> - Returns a spun version of the input
#   spun me <query> - Returns a spintax version of the input using articlemanager.us spinner API
#   spun and spin me <query> - Returns a spun version of the input using spun me command first
#   spin the last spun - Returns a spun version of the user centric input generated by the last spun me call
#
# Author:
#   mmstud

crypto = require 'crypto'
env = process.env

# spin vars
split_str = '|'
replace_regexp_str = /[{}]/gi
match_regexp_str = /{[^{}]+?}/gi

spin = (txt) ->
	if txt
		txt = capture(txt) while txt.match(match_regexp_str)
	txt

capture = (txt) ->
	match = txt.match(match_regexp_str)
	if (match[0])
		words = match[0].split(split_str)
		replace = words[Math.floor(Math.random()*words.length)].replace(replace_regexp_str, '')
		txt = txt.replace(match[0], replace)
	txt

# spun vars. spinner API signup coming soon!
secret_key = env.HUBOT_SPINNER_SECRET_KEY
access_key = env.HUBOT_SPINNER_ACCESS_KEY
host = 'www.articlemanager.us'
path = '/api/spinner.php'
version = '2011-06-24'
scheme = 'http'

gmdatenow = () ->
	g = new Date()
	m = g.getMonth() + 1
	d = g.getDate()
	y = g.getFullYear()
	h = g.getHours()+2
	i = g.getMinutes()
	s = g.getSeconds()
	"#{y}-#{m}-#{d} #{h}:#{i}:#{s}"

get_signature = (host, path, secret_key, access_key, timestamp, version) ->
	newline = "\n"
	request = "timestamp=#{escape(timestamp)}&version=#{escape(version)}&access_key=#{escape(access_key)}"
	data = "GET" + newline + host + newline + path + newline + request
	hmac = crypto.createHmac('sha256', secret_key)
	hmac.update(data)
	hmac.digest('base64')

spun = (msg, spinner = null, robot_brain = null) ->
	timestamp = gmdatenow()
	signature = get_signature(host, path, secret_key, access_key, timestamp, version)
	msg.http(scheme + "://" + host + path)
		.query
			timestamp: timestamp
			version: version
			access_key: access_key
			signature: signature
			type: 'json'
		.post(msg.match[1]) (err, res, body) ->
			if err
				msg.send err
			else if res.statusCode is not 200
				msg.send "Service not available! Status code: " + res.statusCode
			else
				body = JSON.parse(body)
				if body.response is 'error'
					msg.send body.message
				else
					if spinner
						msg.send spinner body.message
					else
						# set to the memory so user can spin it with separate "spin the last spun" command
						if robot_brain
							if not robot_brain.data.spin
								robot_brain.data.spin = []
							robot_brain.data.spin[msg.message.user.reply_to] = body.message
						msg.send body.message

# small factory to support both gtalk and other adapters by hearing all lines or those called by bot name only
hear_and_respond = (robot, regex, callback) ->
	robot.hear eval('/^'+regex+'/i'), callback
	robot.respond eval('/'+regex+'/i'), callback

module.exports = (robot) ->
	hear_and_respond robot, 'spin me ([\\s\\S]*)', (msg) ->
		msg.send spin msg.match[1]

	hear_and_respond robot, 'spun me ([\\s\\S]*)', (msg) ->
		spun(msg, null, robot.brain)

	hear_and_respond robot, 'spun and spin me ([\\s\\S]*)', (msg) ->
		spun(msg, spin)

	hear_and_respond robot, 'spin the last spun$', (msg) ->
		# get user centric input from memory
		if @robot.brain.data.spin[msg.message.user.reply_to]
			msg.send spin robot.brain.data.spin[msg.message.user.reply_to]
		else
			msg.send "Nothing so spin. Please use spun first."
