#!/usr/bin/env python

'''
The deploy.tk Manager server
'''

import sys
import os
import json
import collections
import logging
import traceback

import deploytk
import deploytk.handlers

import pyaas
import pyaas.storage

class Application(pyaas.server.Application):
    def __init__(self):
        self.websockets = set()
        self.foremen    = set()

        self.patterns = [
            ( r'/jobs/(.*)',      deploytk.handlers.manager.Jobs      ),
            ( r'/positions/(.*)', deploytk.handlers.manager.Positions ),
            ( r'/data\.js',       deploytk.handlers.manager.Data      ),
            ( r'/ws',   pyaas.handlers.ws.Protected, {'sockets'  :  self.websockets} ),
            ( r'/',     pyaas.handlers.Protected,    {'template' : 'manager'       } ),
        ]

        pyaas.server.Application.__init__(self, 'manager')

        self.router = deploytk.zmqsockets.Router(recv=self.OnCommand).Bind(port=12001)

    def Broadcast(self, **kwds):
        msg = json.dumps(kwds)
        for client in self.websockets:
            client.write_message(msg)

    def OnCommand(self, args):
        # TODO: should probably verify the integrity of the message
        if len(args) < 2:
            logging.error('Missing action from %s', args[0])
            return

        function = getattr(self, 'On_'+args[1], None)
        if function is None:
            logging.error('Unknown action "%s" from: %s', args[1], args[0])
            return

        function(*args[2:])

    def On_Identify(self, identity):
        identity = json.loads(identity)
        if 'id' not in identity:
            logging.error('id not present, check fqdn')
            return

        logging.debug('Adding foreman: %s', identity['id'])

        # TODO: use it or lose it
        # keep track of active foremen connected to the system
        self.foremen.add(identity['id'])

        try:
            # check if this system has connected before
            foreman = deploytk.records.Foreman.Read(identity['id'])

            if foreman:
                foreman.Update(identity)
                self.Broadcast(action='UpdateForeman', data=identity)

                jobs = deploytk.records.Jobs.Read('foreman = "{0}"'.format(foreman.id))
                self.router.Send(str(foreman.id), 'AddJobs', jobs.json)

            else:
                position = dict(
                    id = identity['id'],
                    x  = 100 * (len(self.foremen) - 1),
                    y  = 0,
                    w  = 100,
                    h  = 100,
                    )

                deploytk.records.Position.Create(position)
                foreman = deploytk.records.Foreman.Create(identity)

                self.Broadcast(action='CreatePosition', data=position)
                self.Broadcast(action='CreateForeman',  data=identity)

        except pyaas.error as e:
            logging.error('%s', e)
            return

def main():
    try:
        pyaas.util.setPrefix()
        pyaas.util.setNameSpace('deploytk')

        pyaas.settings.load('manager')
        pyaas.storage.initialize()

        if pyaas.args.initdb:
            sys.exit(0)

        app = Application()
        try:
            app.Listen()
        except KeyboardInterrupt:
            app.Stop()

    except pyaas.error as e:
        sys.stderr.write('ERROR: %s: %s\n' % (sys.argv[0], e))
        sys.exit(-1)

if '__main__' == __name__:
    main()
