###########################################################################
#
# This program is part of Zenoss Core, an open source monitoring platform.
# Copyright (C) 2007, Zenoss Inc.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 as published by
# the Free Software Foundation.
#
# For complete information please visit: http://www.zenoss.com/oss/
#
###########################################################################

__doc__ = """PythonClient
Python performance data collector client
"""

import logging
log = logging.getLogger("zen.PythonClient")

import Globals

from BaseClient import BaseClient
from twisted.internet.defer import Deferred, DeferredList
from twisted.python.failure import Failure

class PythonClient(BaseClient):
    """
    Implement the DataCollector Client interface for Python
    """


    def __init__(self, device=None, datacollector=None, plugins=[]):
        """
        Initializer

        @param device: remote device to use the datacollector
        @type device: device object
        @param datacollector: performance data collector object
        @type datacollector: datacollector object
        @param plugins: Python-based performance data collector plugin
        @type plugins: list of plugin objects
        """
        BaseClient.__init__(self, device, datacollector)
        self.hostname = device.id
        self.plugins = plugins
        self.results = []


    def run(self):
        """
        Start Python collection.
        """
        deferreds = []
        for plugin in self.plugins:
            log.debug("Running collection for plugin %s", plugin.name())
            r = plugin.collect(self.device, log)
            if isinstance(r, Deferred):
                deferreds.append(r)
                r.addBoth(self.collectComplete, plugin)
            else:
                log.debug("Results for %s: %s", plugin.name(), str(r))
                self.results.append((plugin, r))
        
        dl = DeferredList(deferreds)
        dl.addCallback(self.collectComplete, None)


    def collectComplete(self, r, plugin):
        """
        Twisted deferred error callback used to store the
        results of the collection run

        @param r: result from the collection run
        @type r: result or Exception
        @param plugin: Python-based performance data collector plugin
        @type plugin: plugin object
        """
        if plugin is None:
            self.clientFinished()
            return

        if isinstance(r, Failure):
            log.warn("Error in %s: %s", plugin.name(), r.getErrorMessage())
        else:
            log.debug("Results for %s: %s", plugin.name(), str(r))
            self.results.append((plugin, r))


    def clientFinished(self):
        """
        Stop the collection of performance data
        """
        log.info("Python client finished collection for %s" % self.device.id)
        if self.datacollector:
            self.datacollector.clientFinished(self)


    def getResults(self):
        """
        Return the results of the data collection.
        To be implemented by child classes

        @return: list of results
        @rtype: list of results
        """
        return self.results
