#!/usr/bin/python -u
# -*- mode: python; coding: utf-8 -*-

from __future__ import with_statement

import sys
import threading
import os
import logging

import Ice
cwd = os.path.dirname(__file__)
Ice.loadSlice('-I%s --all %s/atheist.ice' % (Ice.getSliceDir(), cwd))

import Atheist as rath
import atheist
from atheist.manager import Manager

log = logging.getLogger('atheist.server')
log.setLevel(logging.DEBUG)
log.debug('log init')


def get_proxies(adapter, cast, servants):
    proxies = [adapter.addWithUUID(x) for x in servants]
    return [cast.uncheckedCast(x) for x in proxies]


class TaskCaseI(rath.TaskCase):

    def __init__(self, mng, tc):
        self.mng = mng
        self.tc = tc
        self.lock = threading.Lock()

    # from TaskCase interface
    def run(self, current=None):
        self.mng.statusOb.updateTaskCases({self.tc.fname: rath.Status.RUNNING})

        if self.lock.locked(): return

        with self.lock:
            self.tc.run()
            self.mng.statusOb.updateTasks(
                dict([("%s:%s" % (t.fname, t.name),
                       rath.Status(t.result)) for t in self.tc.tasks]))

            self.mng.statusOb.updateTaskCases(
                {self.tc.fname: rath.Status(self.tc.result)})


    # from TaskCase interface
    def getConfig(self, current=None):
        retval = {}
        for task in self.tc.tasks:
            config = rath.TaskConfig(indx=task.indx)
            for name in [x for x in dir(config)
                     if x in atheist.task_attrs.keys()]:
                setattr(config, name, getattr(task, name))
            retval[str(task.indx)] = config

        return retval

    # from TaskCase interface
    def getStatus(self, current=None):
        raise NotImplementedError


class ManagerI(rath.Manager):

    def __init__(self, argv, adap):
        self.mng = Manager(argv)
        self.adap = adap
        self.statusOb = None
        self.outOb = None
        self.logOb = None
        self.cases = []
        self.proxies = []
        self.lock = threading.Lock()

    def refresh(self):
        # FIXME: Se deben eliminar los proxies de los cases que ya no
        # existen y añadir solo los nuevos

        for prx in self.proxies:
            self.adap.remove(prx.ice_getIdentity())

        self.mng.reload()
        self.cases = [TaskCaseI(self,x) for x in self.mng.itercases()]
        self.proxies = get_proxies(self.adap, rath.TaskCasePrx,
                                   self.cases)

        for c in self.mng.itercases():
            print c

        log.info("cases: %s" % len(self.cases))

    # from Manager interface
    def getTaskCases(self, current=None):
        return self.proxies

    # from Manager interface
    def runAll(self, current=None):
        if self.lock.locked():
            log.warning('runAll: Manager is already running .............')
            return

        with self.lock:
            self.refresh()
            self.statusOb.updateManager(rath.Status.RUNNING)
            for tc in self.cases:
                tc.run()
            self.statusOb.updateManager(rath.Status.UNKNOWN)

    # from Manager interface
    def attachStatusOb(self, ob, current=None):
        self.statusOb = ob

    # from Manager interface
    def attachOutOb(self, ob, taskIds, current=None):
        self.outOb = ob

    # from Manager interface
    def attachLogOb(self, ob, taskIds, current=None):
        self.logOb = ob


class server(Ice.Application):

    def run(self, argv):
        self.shutdownOnInterrupt()
        ic = self.communicator()

        adapter = self.communicator().createObjectAdapter("Manager.Adapter")
        oid = ic.getProperties().getProperty("Manager.InstanceName")
        oid = ic.stringToIdentity(oid)
        proxy = adapter.add(ManagerI(argv, adapter), oid)
        adapter.activate()

        log.debug("Manager at '%s'" % proxy)

        self.communicator().waitForShutdown()
        return 0


if __name__ == "__main__":
    sys.exit(server().main(sys.argv[1:]))
