#!/usr/bin/env python
# vim: set fileencoding=utf-8 :

import socket
from select import select
from string import split,strip,join

import jabber


import sys, os
sys.path.insert(1, os.path.join(sys.path[0], '../..'))
sys.path.insert(1, os.path.join(sys.path[0], '../../..'))
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
from logistics.models import *


# Change this to 0 if you dont want a color xterm
USE_COLOR = 1

Who = ''
MyStatus = ''
MyShow   = ''

def usage():
    print "%s: a simple python jabber client " % sys.argv[0]
    print "usage:"
    print "%s <server> - connect to <server> and register" % sys.argv[0]
    print "%s server> <username> <password> <resource>"    % sys.argv[0]
    print "            - connect to server and login   "
    sys.exit(0)


def doCmd(con,txt):
    global Who
    if txt[0] == '/' :
        cmd = split(txt)
        if cmd[0] == '/select':
            Who = cmd[1]
            print "%s selected" % cmd[1]
        elif cmd[0] == '/presence':
            to = cmd[1]
            type = cmd[2]
            con.send(jabber.Presence(to, type))
        elif cmd[0] == '/status':
            p = jabber.Presence()
            MyStatus = ' '.join(cmd[1:])
            p.setStatus(MyStatus)
            con.send(p)
        elif cmd[0] == '/show':
            p = jabber.Presence()
            MyShow = ' '.join(cmd[1:])
            p.setShow(MyShow)
            con.send(p)
        elif cmd[0] == '/subscribe':
            to = cmd[1]
            con.send(jabber.Presence(to, 'subscribe'))
        elif cmd[0] == '/unsubscribe':
            to = cmd[1]
            con.send(jabber.Presence(to, 'unsubscribe'))
        elif cmd[0] == '/roster':
            con.requestRoster()
            _roster = con.getRoster()
            for jid in _roster.getJIDs():
                print colorize("%s :: %s (%s/%s)" 
                               % ( jid, _roster.getOnline(jid),
                                   _roster.getStatus(jid),
                                   _roster.getShow(jid),
                                   ) , 'blue' )

        elif cmd[0] == '/agents':
            print con.requestAgents()
        elif cmd[0] == '/register':
            agent = ''
            if len(cmd) > 1:
                agent = cmd[1]
            con.requestRegInfo(agent)
            print con.getRegInfo()
        elif cmd[0] == '/exit':
            con.disconnect()
            print colorize("Bye!",'red')
            sys.exit(0)
        elif cmd[0] == '/help':
            print "commands are:"
            print "   /select <jabberid>"
            print "      - selects who to send messages to"
            print "   /subscribe <jid>"
            print "      - subscribe to jid's presence"
            print "   /unsubscribe <jid>"
            print "      - unsubscribe to jid's presence"
            print "   /presence <jabberid> <type>"
            print "      - sends a presence of <type> type to the jabber id"
            print "   /status <status>"
            print "      - set your presence status message"
            print "   /show <status>"
            print "      - set your presence show message"
            print "   /roster"
            print "      - requests roster from the server and "
            print "        display a basic dump of it."
            print "   /exit"
            print "      - exit cleanly"
        else:
            print colorize("uh?", 'red')
    else:
        if Who != '':
            msg = jabber.Message(Who, strip(txt))
            msg.setType('chat')
            print "<%s> %s" % (JID, msg.getBody())
            con.send(msg)
        else:
            print colorize('Nobody selected','red')


def send_msg(target, txt):
	global con
	msg = jabber.Message(target, strip(txt))
	msg.setType('chat')
	con.send(msg)

def set_engineer_target(engineer, target):
	from string import atoi
	try:
		client_id = atoi(target)
	except:
		engineer.location = target
		engineer.target = None
	else:
		engineer.location = None
		engineer.target = Client.objects.get(pk=client_id)
	engineer.save()

def messageCB(con, msg):
    """Called when a message is recieved"""
    print "messageCB"
    if msg.getBody(): ## Dont show blank messages ##
        print colorize(
            '<' + str(msg.getFrom()) + '>', 'green'
            ) + ' ' + msg.getBody()

	JIDr = str(msg.getFrom())
	JID = JIDr[:JIDr.find('/')]
	body = msg.getBody()
	print "JID: %s" % JID
	if body[0] == '/':
		# get engineer by JID
		engineers = Engineer.objects.all().filter(jabber=JID)
		if engineers.count() == 0:
			return
		engineer = engineers[0]
		if not engineer.user.is_active:
			return
		print engineer.firstname.encode('utf-8')
		# katrin engineer command processing
		words = body.split()
		words[0] = words[0][1:]
		print "words: %s" % words
		ENGINEER_STATUS = {
			# bot:    	db, russia
			'free': 	(1, u'Свободен'),
			'offline':	(0, u'Недоступен'),
			'move':		(2, u'В дороге'),
			'work':		(3, u'Работаю'),
		}
		if words[0] == 'status':
			if len(words) >= 2 and words[1] in ENGINEER_STATUS.keys():
				if len(words) < 3 and words[1] != 'offline':
					send_msg(JIDr, u'Wrong syntax')
					return
				elif words[1] != 'offline':
					set_engineer_target(engineer, words[2])
				engineer.status = ENGINEER_STATUS[words[1]][0]
				engineer.save(engineer.user)
				send_msg(JIDr, "status: %s" % ENGINEER_STATUS[words[1]][1])
			elif  len(words) >= 3 and words[1] == 'done':
				from string import atoi
				try:
					task_id = atoi(words[2])
				except (ValueError):
					send_msg(JIDr, u"wrong syntax")
					return
				try:
					task = Task.objects.get(pk=task_id)
				except Task.DoesNotExist:
					send_msg(JIDr, u"Task doesn't exist")
					return
				if engineer.pk != task.engineer.pk:
					send_msg(JIDr, u"You haven't permissions to this task")
					return
				task.status = 2 # Done
				task.save(admin=engineer.user)
				engineer.status = ENGINEER_STATUS['free'][0]
				set_engineer_target(engineer, unicode(task.contract.client.pk))
				engineer.save(admin=engineer.user)
				send_msg(JIDr, "apply task status: ok\nYour status: free")
				return

			else:
				send_msg(JIDr, u"Wrong syntax")
				return
			return
		if words[0] == 'info':
			send_msg(JIDr, "balance: %s" % engineer.balance)
			return
		if len(words) == 2 and words[0] in ('confirm', 'unconfirm'):
			try:
				task = Task.objects.get(pk=int(words[1]))
			except:
				send_msg(JIDr, u"Wrong syntax")
				return
			if  task.engineer == engineer and task.status == 0: #Task must have unassign status
				if words[0] == 'confirm':
					task.status = 1 #assigned
					task.confirmed = True
				else:
					task.confirmed = False
				task.save(admin=engineer.user)
				send_msg(JIDr, u"Task assigned to you")	
		if words[0] == 'help':
			send_msg(JIDr, u"""Katrin robot commands
Change status
/status <free|move|work> <object_id|place_str>
/status <offline>
/status <done> <task_id>

Task confirmation
/confirm <task_id>
/unconfirm <task_id>

See info about you
/info

Help
/help""")


def presenceCB(con, prs):
    """Called when a presence is recieved"""
    who = str(prs.getFrom())
    type = prs.getType()
    if type == None: type = 'available'

    # subscription request: 
    # - accept their subscription
    # - send request for subscription to their presence
    if type == 'subscribe':
        print colorize("subscribe request from %s" % (who), 'blue')
        con.send(jabber.Presence(to=who, type='subscribed'))
        con.send(jabber.Presence(to=who, type='subscribe'))

    # unsubscription request: 
    # - accept their unsubscription
    # - send request for unsubscription to their presence
    elif type == 'unsubscribe':
        print colorize("unsubscribe request from %s" % (who), 'blue')
        con.send(jabber.Presence(to=who, type='unsubscribed'))
        con.send(jabber.Presence(to=who, type='unsubscribe'))

    elif type == 'subscribed':
        print colorize("we are now subscribed to %s" % (who), 'blue')

    elif type == 'unsubscribed':
        print colorize("we are now unsubscribed to %s"  % (who), 'blue')

    elif type == 'available':
        print colorize("%s is available (%s / %s)" % \
                       (who, prs.getShow(), prs.getStatus()),'blue')
    elif type == 'unavailable':
        print colorize("%s is unavailable (%s / %s)" % \
                       (who, prs.getShow(), prs.getStatus()),'blue')


def iqCB(con,iq):
    """Called when an iq is recieved, we just let the library handle it at the moment"""
    pass

def disconnectedCB(con):
    print colorize("Ouch, network error", 'red')
    sys.exit(1)

def colorize(txt, col):
    """Return colorized text"""
    if not USE_COLOR: return txt ## DJ - just incase it breaks your terms ;) ##
    cols = { 'red':1, 'green':2, 'yellow':3, 'blue':4}
    initcode = '\033[;3'
    endcode  = '\033[0m'
    if type(col) == type(1): 
        return initcode + str(col) + 'm' + txt + endcode
    try: return initcode + str(cols[col]) + 'm' + txt + endcode
    except: return txt


if len(sys.argv) == 1: usage()
Server = sys.argv[1]
Username = ''
Password = ''
Resource = 'default'


con = jabber.Client(host=Server, debug=0 ,log=sys.stderr)

# Experimental SSL support
#
# con = jabber.Client(host=Server, debug=1 ,log=sys.stderr,
#                    port=5223, connection=xmlstream.TCP_SSL)

try:
    con.connect()
except IOError, e:
    print "Couldn't connect: %s" % e
    sys.exit(0)
else:
    print colorize("Connected",'red')

con.setMessageHandler(messageCB)
con.setPresenceHandler(presenceCB)
con.setIqHandler(iqCB)
con.setDisconnectHandler(disconnectedCB)

if len(sys.argv) == 2:
    # Set up a jabber account
    con.requestRegInfo()
    req = con.getRegInfo()
    print req[u'instructions']
    for info in req.keys():
        if info != u'instructions' and \
           info != u'key':
            print "enter %s;" % info
            con.setRegInfo( info,strip(sys.stdin.readline()) )
    con.sendRegInfo()
    req = con.getRegInfo()
    Username = req['username']
    Password = req['password']
else:
    Username = sys.argv[2]
    Password = sys.argv[3]
    Resource = sys.argv[4]

print colorize("Attempting to log in...", 'red')


if con.auth(Username,Password,Resource):
    print colorize("Logged in as %s to server %s" % ( Username, Server), 'red')
else:
    print "eek -> ", con.lastErr, con.lastErrCode
    sys.exit(1)

print colorize("Requesting Roster Info" , 'red')
con.requestRoster()
con.sendInitPresence()
print colorize("Ok, ready" , 'red')
print colorize("Type /help for help", 'red')

JID = Username + '@' + Server + '/' + Resource

import threading, time
class CheckTaskThread(threading.Thread):
	"""Check new assigned task and inform about it"""
	def run(self):
		while 1:
			print 'CheckTaskThread'
			# get not assigned and not confirmed tasks
			for task in Task.objects.filter(confirmed=None, status=0):
				send_msg(task.engineer.jabber, 
"""You have new task number %s.
Desc: %s
Client: %s
Address: %s

You need send command:
/confirm %s
or
/unconfirm %s""" % (
				task.id,
				task.description,
				task.contract.client,
				task.contract.client.yu_address,
				task.id,
				task.id,
				))
			time.sleep(600)

CheckTaskThread().start()



while(1):
    inputs, outputs, errors = select([sys.stdin], [], [],1)

    if sys.stdin in inputs:
        doCmd(con,sys.stdin.readline())
    else:
        con.process(1)
    
        









