﻿# -*- coding: UTF-8 -*-
import xmpp
from xmpp import *

def init(bot):
    if not hasattr(bot, 'Commands'):
        disco = xmpp.browser.Browser()
        disco.PlugIn(bot)
        commands = xmpp.commands.Commands(disco)
        commands.PlugIn(bot)
    commands = bot.Commands
    command_test = TestCommand()
    command_test.plugin(commands)
    return -1 #system


  
class TestCommand(xmpp.commands.Command_Handler_Prototype):
	""" Example class. You should read source if you wish to understate how it works. This one
	    actually does some calculations."""
	name = 'testcommand'
	description = 'Circle calculations'
	def __init__(self, jid=''):
		""" Initialize some internals. Set the first request handler to self.calcTypeForm.
		"""
		xmpp.commands.Command_Handler_Prototype.__init__(self,jid)
		self.initial = {
			'execute': self.initialForm
		}

	def initialForm(self, conn, request):
		""" Assign a session id and send the first form. """
		sessionid = self.getSessionID()
		self.sessions[sessionid] = {
			'jid':request.getFrom(),
			'data':{'type':None}
		}

		# simulate that the client sent sessionid, so calcTypeForm will be able
		# to continue
		request.getTag(name="command").setAttr('sessionid', sessionid)

		return self.calcTypeForm(conn, request)
			
	def calcTypeForm(self, conn, request):
		""" Send first form to the requesting user. """
		# get the session data
		sessionid = request.getTagAttr('command','sessionid')
		session = self.sessions[sessionid]

		# What to do when a user sends us a response? Note, that we should always
		# include 'execute', as it is a default action when requester does not send
		# exact action to do (should be set to the same as 'next' or 'complete' fields)
		session['actions'] = {
			'cancel': self.cancel,
			'next': self.calcTypeFormAccept,
			'execute': self.calcTypeFormAccept,
		}

		# The form to send
		calctypefield = xmpp.DataField(
			name='calctype',
			desc='Calculation Type',
			value=session['data']['type'],
			options=[
				['Calculate the diameter of a circle','circlediameter'],
				['Calculate the area of a circle','circlearea']
			],
			typ='list-single',
			required=1)

		# We set label attribute... seems that the xmpppy.DataField cannot do that
		calctypefield.setAttr('label', 'Calculation Type')

		form = xmpp.DataForm(
			title='Select type of operation',
			data=[
				'Use the combobox to select the type of calculation you would like'\
				'to do, then click Next.',
				calctypefield])

		# Build a reply with the form
		reply = request.buildReply('result')
		replypayload = [
			xmpp.Node('actions',
				attrs={'execute':'next'},
				payload=[xmpp.Node('next')]),
			form]
		reply.addChild(
			name='command',
			namespace=NS_COMMANDS,
			attrs={
				'node':request.getTagAttr('command','node'),
				'sessionid':sessionid,
				'status':'executing'},
			payload=replypayload)
		self._owner.send(reply)	# Question: self._owner or conn?
		raise xmpp.NodeProcessed

	def calcTypeFormAccept(self, conn, request):
		""" Load the calcType form filled in by requester, then reply with
		    the second form. """
		# get the session data
		sessionid = request.getTagAttr('command','sessionid')
		session = self.sessions[sessionid]

		# load the form
		node = request.getTag(name='command').getTag(name='x',namespace=NS_DATA)
		form = xmpp.DataForm(node=node)

		# retrieve the data
		session['data']['type'] = form.getField('calctype').getValue()

		# send second form
		return self.calcDataForm(conn, request)

	def calcDataForm(self, conn, request, notavalue=None):
		""" Send a form asking for diameter. """
		# get the session data
		sessionid = request.getTagAttr('command','sessionid')
		session = self.sessions[sessionid]

		# set the actions taken on requester's response
		session['actions'] = {
			'cancel': self.cancel,
			'prev': self.calcTypeForm,
			'next': self.calcDataFormAccept,
			'execute': self.calcDataFormAccept
		}

		# create a form
		radiusfield = xmpp.DataField(desc='Radius',name='radius',typ='text-single')
		radiusfield.setAttr('label', 'Radius')

		form = xmpp.DataForm(
			title = 'Enter the radius',
			data=[
				'Enter the radius of the circle (numbers only)',
				radiusfield])

		# build a reply stanza
		reply = request.buildReply('result')
		replypayload = [
			xmpp.Node('actions',
				attrs={'execute':'complete'},
				payload=[xmpp.Node('complete'),xmpp.Node('prev')]),
			form]

		if notavalue:
			replypayload.append(xmpp.Node('note',
				attrs={'type': 'warn'},
				payload=['You have to enter valid number.']))

		reply.addChild(
			name='command',
			namespace=NS_COMMANDS,
			attrs={
				'node':request.getTagAttr('command','node'),
				'sessionid':request.getTagAttr('command','sessionid'),
				'status':'executing'},
			payload=replypayload)

		self._owner.send(reply)
		raise xmpp.NodeProcessed

	def calcDataFormAccept(self, conn, request):
		""" Load the calcType form filled in by requester, then reply with the result. """
		# get the session data
		sessionid = request.getTagAttr('command','sessionid')
		session = self.sessions[sessionid]

		# load the form
		node = request.getTag(name='command').getTag(name='x',namespace=NS_DATA)
		form = xmpp.DataForm(node=node)

		# retrieve the data; if the entered value is not a number, return to second stage
		try:
			value = float(form.getField('radius').getValue())
		except:
			self.calcDataForm(conn, request, notavalue=True)

		# calculate the answer
		from math import pi
		if session['data']['type'] == 'circlearea':
			result = (value**2) * pi
		else:
			result = 2 * value * pi

		# build the result form
		form = xmpp.DataForm(
			typ='result',
			data=[xmpp.DataField(desc='result', name='result', value=result)])

		# build the reply stanza
		reply = request.buildReply('result')
		reply.addChild(
			name='command',
			namespace=NS_COMMANDS,
			attrs={
				'node':request.getTagAttr('command','node'),
				'sessionid':sessionid,
				'status':'completed'},
			payload=[form])

		self._owner.send(reply)

		# erase the data about session
		del self.sessions[sessionid]

		raise xmpp.NodeProcessed

	def cancel(self, conn, request):
		""" Requester canceled the session, send a short reply. """
		# get the session id
		sessionid = request.getTagAttr('command','sessionid')

		# send the reply
		reply = request.buildReply('result')
		reply.addChild(
			name='command',
			namespace=NS_COMMANDS,
			attrs={
				'node':request.getTagAttr('command','node'),
				'sessionid':sessionid,
				'status':'cancelled'})
		self._owner.send(reply)

		# erase the data about session
		del self.sessions[sessionid]

		raise xmpp.NodeProcessed