#!/usr/bin/env python
#coding: utf-8
from __future__ import unicode_literals, print_function
from kasaya import control
import plac, datetime
import os


def run_kasaya_daemon():
    """
    Kasaya daemon is not regular kasaya service, it must be run in special way.
    This funcion is doing it.
    """
    from kasaya.core.lib.servicesctl import Service
    from kasaya.workers import kasayad
    pth = os.path.dirname(kasayad.__file__)
    srv = Service(pth, kasayad_mode=True)
    srv.start_service()




class Jobs(object):
    commands = ['boot', 'list', 'rescan', 'wrkstop', 'wrkstats', 'svcstart', 'svcstop']

    #def __init__(self):
    #    pass

    @plac.annotations(
        u=("Show ID identifiers", "flag"),
        hi=("Hide offline services", "flag"),
    )
    def list(self, u=False, hi=False):
        """
        List all hosts and workers running in service bus
        """
        hostline     = "  {service: >{ws}}  {addr: <{wi}} (hostname: {hostname})"
        workerline   = "  {service: >{ws}}  address: {addr} {extra}"
        inactiveline = "  {service: >{ws}}  off"

        if u:
            hostline   += "   ID: {id}"
            workerline += "   ID: {id}  pid: {pid}"

        # all hosts in network
        hosts = control.svbus.status()

        # maximum length of names
        whst, wip, wsvc = 5,0,0
        for h in hosts:
            if h['hostname'] is None:
                h['hostname'] = "-"
            whst = max(whst, len(h['hostname']) )
            wip  = max(wip, len(h['addr']) )
            for s in h['services']:
                wsvc = max(wsvc, len(s['service']) )

        # report
        hcnt, wcnt = 0,0
        for h in hosts:
            hcnt += 1
            print ( hostline.format(wh=whst, wi=wip, ws=wsvc, service="KASAYAD", **h) )

            inact = []
            for w in h['services']:
                # if worker is not managed,
                # which means that this worker is not existing in local services set
                # and cannot be started after shutting down by syncd daemon,
                # then show exclamation let know about this
                if not w['managed']:
                    w['extra'] = "[!]"
                else:
                    w['extra'] = "   "

                if not w['running']:
                    inact.append( w['service'])
                    continue

                wcnt += 1
                print ( workerline.format(ws=wsvc, **w) )

            # inactive services
            if (not hi) and (len(inact)>0):
                for sv in inact:
                    print ( inactiveline.format(ws=wsvc, service=sv) )

            print ()

        print ("Total number of hosts: {0}, running services: {1}".format(hcnt, wcnt) )



    @plac.annotations(
        ID=("ID of worker to stop"),
        terminate=("Use pid rather then ID", "flag"),
        sigkill=("Send SIGKILL (if everything else fails)", "flag")
    )
    def wrkstop(self, ID, terminate=False, sigkill=False):
        """
        Send stop signal to worker with specified ID. If worker is currently
        processing task, it will stop after finishing current job.
        """
        control.worker.stop(ID, terminate, sigkill)


    @plac.annotations(
        ID=("ID of worker to show stats")
    )
    def wrkstats(self, ID):
        """
        Send stop signal to worker with specified ID. If worker is currently
        processing task, worker will stop after finishing current job.
        """
        res = control.worker.stats(ID)
        if res is None:
            print ("Worker not found (ID: %s)" % ID)
            return

        uptime = str( datetime.timedelta(seconds=res['uptime'] ) )

        ln = "{0:>26}: {1}"
        print (ln.format("service name",res['service']))
        addr = "%s:%i" % (res['ip'], res['port'])
        print ( ln.format("address", addr) )
        print ( ln.format("used memory", "{:,} KB".format(res['mem_total'])) )
        print ( ln.format("uptime", uptime) )
        ttot = res['task_err'] + res['task_ctl'] + res['task_succ']
        print ( ln.format("total processed tasks", ttot) )
        print ( ln.format("successfull tasks", res['task_succ']) )
        print ( ln.format("error tasks", res['task_err']) )
        print ( ln.format("control tasks", res['task_ctl']) )
        print ( ln.format("non existing method calls", res['task_nonx']) )


    @plac.annotations(
        name=("name of the service to start"),
        ip=("IP of host on which service should be started")
    )
    def svcstart(self, name, ip=None):
        """
        Start service on current host or on remote host with given ip address
        """
        res = control.service.start(name, ip)


    @plac.annotations(
        servicename=("name of the service to stop"),
        ip=("IP of host on which service should be stopped")
    )
    def svcstop(self, servicename, ip=None):
        """
        Stop one service with given name on current host,
        or on remote host if IP parameter is given.
        """
        control.service.stop(servicename, ip)


    @plac.annotations(
        ip=("IP of host on which service should be rescanned")
    )
    def rescan(self, ip=None):
        """
        Force kasaya daemon to rescan available services.
        This allow to add or remove available services on host
        on the fly, without restarting kasaya daemon.
        """
        control.host.rescan(ip)


    @plac.annotations( )
    def boot(self):
        """
        Start local instance of kasaya daemon.
        """
        run_kasaya_daemon()



if __name__=="__main__":
    #from kasaya.conf import settings
    #print (settings.SERVICE_BUS_NAME)
    plac.call( Jobs() )
