# tinfoil: a simple wrapper around cooker for bitbake-based command-line utilities
#
# Copyright (C) 2012-2017 Intel Corporation
# Copyright (C) 2011 Mentor Graphics Corporation
# Copyright (C) 2006-2012 Richard Purdie
#
# 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.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

import logging
import os
import sys
import atexit
import re
from collections import OrderedDict, defaultdict

import bb.cache
import bb.cooker
import bb.providers
import bb.taskdata
import bb.utils
import bb.command
import bb.remotedata
from bb.cookerdata import CookerConfiguration, ConfigParameters
from bb.main import setup_bitbake, BitBakeConfigParameters, BBMainException
import bb.fetch2


# We need this in order to shut down the connection to the bitbake server,
# otherwise the process will never properly exit
_server_connections = []
def _terminate_connections():
    for connection in _server_connections:
        connection.terminate()
atexit.register(_terminate_connections)

class TinfoilUIException(Exception):
    """Exception raised when the UI returns non-zero from its main function"""
    def __init__(self, returncode):
        self.returncode = returncode
    def __repr__(self):
        return 'UI module main returned %d' % self.returncode

class TinfoilCommandFailed(Exception):
    """Exception raised when run_command fails"""

class TinfoilDataStoreConnector:
    """Connector object used to enable access to datastore objects via tinfoil"""

    def __init__(self, tinfoil, dsindex):
        self.tinfoil = tinfoil
        self.dsindex = dsindex
    def getVar(self, name):
        value = self.tinfoil.run_command('dataStoreConnectorFindVar', self.dsindex, name)
        overrides = None
        if isinstance(value, dict):
            if '_connector_origtype' in value:
                value['_content'] = self.tinfoil._reconvert_type(value['_content'], value['_connector_origtype'])
                del value['_connector_origtype']
            if '_connector_overrides' in value:
                overrides = value['_connector_overrides']
                del value['_connector_overrides']
        return value, overrides
    def getKeys(self):
        return set(self.tinfoil.run_command('dataStoreConnectorGetKeys', self.dsindex))
    def getVarHistory(self, name):
        return self.tinfoil.run_command('dataStoreConnectorGetVarHistory', self.dsindex, name)
    def expandPythonRef(self, varname, expr, d):
        ds = bb.remotedata.RemoteDatastores.transmit_datastore(d)
        ret = self.tinfoil.run_command('dataStoreConnectorExpandPythonRef', ds, varname, expr)
        return ret
    def setVar(self, varname, value):
        if self.dsindex is None:
            self.tinfoil.run_command('setVariable', varname, value)
        else:
            # Not currently implemented - indicate that setting should
            # be redirected to local side
            return True
    def setVarFlag(self, varname, flagname, value):
        if self.dsindex is None:
            self.tinfoil.run_command('dataStoreConnectorSetVarFlag', self.dsindex, varname, flagname, value)
        else:
            # Not currently implemented - indicate that setting should
            # be redirected to local side
            return True
    def delVar(self, varname):
        if self.dsindex is None:
            self.tinfoil.run_command('dataStoreConnectorDelVar', self.dsindex, varname)
        else:
            # Not currently implemented - indicate that setting should
            # be redirected to local side
            return True
    def delVarFlag(self, varname, flagname):
        if self.dsindex is None:
            self.tinfoil.run_command('dataStoreConnectorDelVar', self.dsindex, varname, flagname)
        else:
            # Not currently implemented - indicate that setting should
            # be redirected to local side
            return True
    def renameVar(self, name, newname):
        if self.dsindex is None:
            self.tinfoil.run_command('dataStoreConnectorRenameVar', self.dsindex, name, newname)
        else:
            # Not currently implemented - indicate that setting should
            # be redirected to local side
            return True

class TinfoilCookerAdapter:
    """
    Provide an adapter for existing code that expects to access a cooker object via Tinfoil,
    since now Tinfoil is on the client side it no longer has direct access.
    """

    class TinfoilCookerCollectionAdapter:
        """ cooker.collection adapter """
        def __init__(self, tinfoil):
            self.tinfoil = tinfoil
        def get_file_appends(self, fn):
            return self.tinfoil.get_file_appends(fn)
        def __getattr__(self, name):
            if name == 'overlayed':
                return self.tinfoil.get_overlayed_recipes()
            elif name == 'bbappends':
                return self.tinfoil.run_command('getAllAppends')
            else:
                raise AttributeError("%s instance has no attribute '%s'" % (self.__class__.__name__, name))

    class TinfoilRecipeCacheAdapter:
        """ cooker.recipecache adapter """
        def __init__(self, tinfoil):
            self.tinfoil = tinfoil
            self._cache = {}

        def get_pkg_pn_fn(self):
            pkg_pn = defaultdict(list, self.tinfoil.run_command('getRecipes') or [])
            pkg_fn = {}
            for pn, fnlist in pkg_pn.items():
                for fn in fnlist:
                    pkg_fn[fn] = pn
            self._cache['pkg_pn'] = pkg_pn
            self._cache['pkg_fn'] = pkg_fn

        def __getattr__(self, name):
            # Grab these only when they are requested since they aren't always used
            if name in self._cache:
                return self._cache[name]
            elif name == 'pkg_pn':
                self.get_pkg_pn_fn()
                return self._cache[name]
            elif name == 'pkg_fn':
                self.get_pkg_pn_fn()
                return self._cache[name]
            elif name == 'deps':
                attrvalue = defaultdict(list, self.tinfoil.run_command('getRecipeDepends') or [])
            elif name == 'rundeps':
                attrvalue = defaultdict(lambda: defaultdict(list), self.tinfoil.run_command('getRuntimeDepends') or [])
            elif name == 'runrecs':
                attrvalue = defaultdict(lambda: defaultdict(list), self.tinfoil.run_command('getRuntimeRecommends') or [])
            elif name == 'pkg_pepvpr':
                attrvalue = self.tinfoil.run_command('getRecipeVersions') or {}
            elif name == 'inherits':
                attrvalue = self.tinfoil.run_command('getRecipeInherits') or {}
            elif name == 'bbfile_priority':
                attrvalue = self.tinfoil.run_command('getBbFilePriority') or {}
            elif name == 'pkg_dp':
                attrvalue = self.tinfoil.run_command('getDefaultPreference') or {}
            elif name == 'fn_provides':
                attrvalue = self.tinfoil.run_command('getRecipeProvides') or {}
            elif name == 'packages':
                attrvalue = self.tinfoil.run_command('getRecipePackages') or {}
            elif name == 'packages_dynamic':
                attrvalue = self.tinfoil.run_command('getRecipePackagesDynamic') or {}
            elif name == 'rproviders':
                attrvalue = self.tinfoil.run_command('getRProviders') or {}
            else:
                raise AttributeError("%s instance has no attribute '%s'" % (self.__class__.__name__, name))

            self._cache[name] = attrvalue
            return attrvalue

    def __init__(self, tinfoil):
        self.tinfoil = tinfoil
        self.collection = self.TinfoilCookerCollectionAdapter(tinfoil)
        self.recipecaches = {}
        # FIXME all machines
        self.recipecaches[''] = self.TinfoilRecipeCacheAdapter(tinfoil)
        self._cache = {}
    def __getattr__(self, name):
        # Grab these only when they are requested since they aren't always used
        if name in self._cache:
            return self._cache[name]
        elif name == 'skiplist':
            attrvalue = self.tinfoil.get_skipped_recipes()
        elif name == 'bbfile_config_priorities':
            ret = self.tinfoil.run_command('getLayerPriorities')
            bbfile_config_priorities = []
            for collection, pattern, regex, pri in ret:
                bbfile_config_priorities.append((collection, pattern, re.compile(regex), pri))

            attrvalue = bbfile_config_priorities
        else:
            raise AttributeError("%s instance has no attribute '%s'" % (self.__class__.__name__, name))

        self._cache[name] = attrvalue
        return attrvalue

    def findBestProvider(self, pn):
        return self.tinfoil.find_best_provider(pn)


class TinfoilRecipeInfo:
    """
    Provides a convenient representation of the cached information for a single recipe.
    Some attributes are set on construction, others are read on-demand (which internally
    may result in a remote procedure call to the bitbake server the first time).
    Note that only information which is cached is available through this object - if
    you need other variable values you will need to parse the recipe using
    Tinfoil.parse_recipe().
    """
    def __init__(self, recipecache, d, pn, fn, fns):
        self._recipecache = recipecache
        self._d = d
        self.pn = pn
        self.fn = fn
        self.fns = fns
        self.inherit_files = recipecache.inherits[fn]
        self.depends = recipecache.deps[fn]
        (self.pe, self.pv, self.pr) = recipecache.pkg_pepvpr[fn]
        self._cached_packages = None
        self._cached_rprovides = None
        self._cached_packages_dynamic = None

    def __getattr__(self, name):
        if name == 'alternates':
            return [x for x in self.fns if x != self.fn]
        elif name == 'rdepends':
            return self._recipecache.rundeps[self.fn]
        elif name == 'rrecommends':
            return self._recipecache.runrecs[self.fn]
        elif name == 'provides':
            return self._recipecache.fn_provides[self.fn]
        elif name == 'packages':
            if self._cached_packages is None:
                self._cached_packages = []
                for pkg, fns in self._recipecache.packages.items():
                    if self.fn in fns:
                        self._cached_packages.append(pkg)
            return self._cached_packages
        elif name == 'packages_dynamic':
            if self._cached_packages_dynamic is None:
                self._cached_packages_dynamic = []
                for pkg, fns in self._recipecache.packages_dynamic.items():
                    if self.fn in fns:
                        self._cached_packages_dynamic.append(pkg)
            return self._cached_packages_dynamic
        elif name == 'rprovides':
            if self._cached_rprovides is None:
                self._cached_rprovides = []
                for pkg, fns in self._recipecache.rproviders.items():
                    if self.fn in fns:
                        self._cached_rprovides.append(pkg)
            return self._cached_rprovides
        else:
            raise AttributeError("%s instance has no attribute '%s'" % (self.__class__.__name__, name))
    def inherits(self, only_recipe=False):
        """
        Get the inherited classes for a recipe. Returns the class names only.
        Parameters:
            only_recipe: True to return only the classes inherited by the recipe
                         itself, False to return all classes inherited within
                         the context for the recipe (which includes globally
                         inherited classes).
        """
        if only_recipe:
            global_inherit = [x for x in (self._d.getVar('BBINCLUDED') or '').split() if x.endswith('.bbclass')]
        else:
            global_inherit = []
        for clsfile in self.inherit_files:
            if only_recipe and clsfile in global_inherit:
                continue
            clsname = os.path.splitext(os.path.basename(clsfile))[0]
            yield clsname
    def __str__(self):
        return '%s' % self.pn


class Tinfoil:
    """
    Tinfoil - an API for scripts and utilities to query
    BitBake internals and perform build operations.
    """

    def __init__(self, output=sys.stdout, tracking=False, setup_logging=True):
        """
        Create a new tinfoil object.
        Parameters:
            output: specifies where console output should be sent. Defaults
                    to sys.stdout.
            tracking: True to enable variable history tracking, False to
                    disable it (default). Enabling this has a minor
                    performance impact so typically it isn't enabled
                    unless you need to query variable history.
            setup_logging: True to setup a logger so that things like
                    bb.warn() will work immediately and timeout warnings
                    are visible; False to let BitBake do this itself.
        """
        self.logger = logging.getLogger('BitBake')
        self.config_data = None
        self.cooker = None
        self.tracking = tracking
        self.ui_module = None
        self.server_connection = None
        self.recipes_parsed = False
        self.quiet = 0
        self.oldhandlers = self.logger.handlers[:]
        if setup_logging:
            # This is the *client-side* logger, nothing to do with
            # logging messages from the server
            bb.msg.logger_create('BitBake', output)
            self.localhandlers = []
            for handler in self.logger.handlers:
                if handler not in self.oldhandlers:
                    self.localhandlers.append(handler)

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        self.shutdown()

    def prepare(self, config_only=False, config_params=None, quiet=0, extra_features=None):
        """
        Prepares the underlying BitBake system to be used via tinfoil.
        This function must be called prior to calling any of the other
        functions in the API.
        NOTE: if you call prepare() you must absolutely call shutdown()
        before your code terminates. You can use a "with" block to ensure
        this happens e.g.

            with bb.tinfoil.Tinfoil() as tinfoil:
                tinfoil.prepare()
                ...

        Parameters:
            config_only: True to read only the configuration and not load
                        the cache / parse recipes. This is useful if you just
                        want to query the value of a variable at the global
                        level or you want to do anything else that doesn't
                        involve knowing anything about the recipes in the
                        current configuration. False loads the cache / parses
                        recipes.
            config_params: optionally specify your own configuration
                        parameters. If not specified an instance of
                        TinfoilConfigParameters will be created internally.
            quiet:      quiet level controlling console output - equivalent
                        to bitbake's -q/--quiet option. Default of 0 gives
                        the same output level as normal bitbake execution.
            extra_features: extra features to be added to the feature
                        set requested from the server. See
                        CookerFeatures._feature_list for possible
                        features.
        """
        self.quiet = quiet

        if self.tracking:
            extrafeatures = [bb.cooker.CookerFeatures.BASEDATASTORE_TRACKING]
        else:
            extrafeatures = []

        if extra_features:
            extrafeatures += extra_features

        if not config_params:
            config_params = TinfoilConfigParameters(config_only=config_only, quiet=quiet)

        cookerconfig = CookerConfiguration()
        cookerconfig.setConfigParameters(config_params)

        if not config_only:
            # Disable local loggers because the UI module is going to set up its own
            for handler in self.localhandlers:
                self.logger.handlers.remove(handler)
            self.localhandlers = []

        self.server_connection, ui_module = setup_bitbake(config_params,
                            cookerconfig,
                            extrafeatures)

        self.ui_module = ui_module

        # Ensure the path to bitbake's bin directory is in PATH so that things like
        # bitbake-worker can be run (usually this is the case, but it doesn't have to be)
        path = os.getenv('PATH').split(':')
        bitbakebinpath = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', 'bin'))
        for entry in path:
            if entry.endswith(os.sep):
                entry = entry[:-1]
            if os.path.abspath(entry) == bitbakebinpath:
                break
        else:
            path.insert(0, bitbakebinpath)
            os.environ['PATH'] = ':'.join(path)

        if self.server_connection:
            _server_connections.append(self.server_connection)
            if config_only:
                config_params.updateToServer(self.server_connection.connection, os.environ.copy())
                self.run_command('parseConfiguration')
            else:
                self.run_actions(config_params)
                self.recipes_parsed = True

            self.config_data = bb.data.init()
            connector = TinfoilDataStoreConnector(self, None)
            self.config_data.setVar('_remote_data', connector)
            self.cooker = TinfoilCookerAdapter(self)
            self.cooker_data = self.cooker.recipecaches['']
        else:
            raise Exception('Failed to start bitbake server')

    def run_actions(self, config_params):
        """
        Run the actions specified in config_params through the UI.
        """
        ret = self.ui_module.main(self.server_connection.connection, self.server_connection.events, config_params)
        if ret:
            raise TinfoilUIException(ret)

    def parseRecipes(self):
        """
        Legacy function - use parse_recipes() instead.
        """
        self.parse_recipes()

    def parse_recipes(self):
        """
        Load information on all recipes. Normally you should specify
        config_only=False when calling prepare() instead of using this
        function; this function is designed for situations where you need
        to initialise Tinfoil and use it with config_only=True first and
        then conditionally call this function to parse recipes later.
        """
        config_params = TinfoilConfigParameters(config_only=False)
        self.run_actions(config_params)
        self.recipes_parsed = True

    def run_command(self, command, *params):
        """
        Run a command on the server (as implemented in bb.command).
        Note that there are two types of command - synchronous and
        asynchronous; in order to receive the results of asynchronous
        commands you will need to set an appropriate event mask
        using set_event_mask() and listen for the result using
        wait_event() - with the correct event mask you'll at least get
        bb.command.CommandCompleted and possibly other events before
        that depending on the command.
        """
        if not self.server_connection:
            raise Exception('Not connected to server (did you call .prepare()?)')

        commandline = [command]
        if params:
            commandline.extend(params)
        result = self.server_connection.connection.runCommand(commandline)
        if result[1]:
            raise TinfoilCommandFailed(result[1])
        return result[0]

    def set_event_mask(self, eventlist):
        """Set the event mask which will be applied within wait_event()"""
        if not self.server_connection:
            raise Exception('Not connected to server (did you call .prepare()?)')
        llevel, debug_domains = bb.msg.constructLogOptions()
        ret = self.run_command('setEventMask', self.server_connection.connection.getEventHandle(), llevel, debug_domains, eventlist)
        if not ret:
            raise Exception('setEventMask failed')

    def wait_event(self, timeout=0):
        """
        Wait for an event from the server for the specified time.
        A timeout of 0 means don't wait if there are no events in the queue.
        Returns the next event in the queue or None if the timeout was
        reached. Note that in order to recieve any events you will
        first need to set the internal event mask using set_event_mask()
        (otherwise whatever event mask the UI set up will be in effect).
        """
        if not self.server_connection:
            raise Exception('Not connected to server (did you call .prepare()?)')
        return self.server_connection.events.waitEvent(timeout)

    def get_overlayed_recipes(self):
        """
        Find recipes which are overlayed (i.e. where recipes exist in multiple layers)
        """
        return defaultdict(list, self.run_command('getOverlayedRecipes'))

    def get_skipped_recipes(self):
        """
        Find recipes which were skipped (i.e. SkipRecipe was raised
        during parsing).
        """
        return OrderedDict(self.run_command('getSkippedRecipes'))

    def get_all_providers(self):
        return defaultdict(list, self.run_command('allProviders'))

    def find_providers(self):
        return self.run_command('findProviders')

    def find_best_provider(self, pn):
        return self.run_command('findBestProvider', pn)

    def get_runtime_providers(self, rdep):
        return self.run_command('getRuntimeProviders', rdep)

    def get_recipe_file(self, pn):
        """
        Get the file name for the specified recipe/target. Raises
        bb.providers.NoProvider if there is no match or the recipe was
        skipped.
        """
        best = self.find_best_provider(pn)
        if not best or (len(best) > 3 and not best[3]):
            skiplist = self.get_skipped_recipes()
            taskdata = bb.taskdata.TaskData(None, skiplist=skiplist)
            skipreasons = taskdata.get_reasons(pn)
            if skipreasons:
                raise bb.providers.NoProvider('%s is unavailable:\n  %s' % (pn, '  \n'.join(skipreasons)))
            else:
                raise bb.providers.NoProvider('Unable to find any recipe file matching "%s"' % pn)
        return best[3]

    def get_file_appends(self, fn):
        """
        Find the bbappends for a recipe file
        """
        return self.run_command('getFileAppends', fn)

    def all_recipes(self, mc='', sort=True):
        """
        Enable iterating over all recipes in the current configuration.
        Returns an iterator over TinfoilRecipeInfo objects created on demand.
        Parameters:
            mc: The multiconfig, default of '' uses the main configuration.
            sort: True to sort recipes alphabetically (default), False otherwise
        """
        recipecache = self.cooker.recipecaches[mc]
        if sort:
            recipes = sorted(recipecache.pkg_pn.items())
        else:
            recipes = recipecache.pkg_pn.items()
        for pn, fns in recipes:
            prov = self.find_best_provider(pn)
            recipe = TinfoilRecipeInfo(recipecache,
                                       self.config_data,
                                       pn=pn,
                                       fn=prov[3],
                                       fns=fns)
            yield recipe

    def all_recipe_files(self, mc='', variants=True, preferred_only=False):
        """
        Enable iterating over all recipe files in the current configuration.
        Returns an iterator over file paths.
        Parameters:
            mc: The multiconfig, default of '' uses the main configuration.
            variants: True to include variants of recipes created through
                      BBCLASSEXTEND (default) or False to exclude them
            preferred_only: True to include only the preferred recipe where
                      multiple exist providing the same PN, False to list
                      all recipes
        """
        recipecache = self.cooker.recipecaches[mc]
        if preferred_only:
            files = []
            for pn in recipecache.pkg_pn.keys():
                prov = self.find_best_provider(pn)
                files.append(prov[3])
        else:
            files = recipecache.pkg_fn.keys()
        for fn in sorted(files):
            if not variants and fn.startswith('virtual:'):
                continue
            yield fn


    def get_recipe_info(self, pn, mc=''):
        """
        Get information on a specific recipe in the current configuration by name (PN).
        Returns a TinfoilRecipeInfo object created on demand.
        Parameters:
            mc: The multiconfig, default of '' uses the main configuration.
        """
        recipecache = self.cooker.recipecaches[mc]
        prov = self.find_best_provider(pn)
        fn = prov[3]
        actual_pn = recipecache.pkg_fn[fn]
        recipe = TinfoilRecipeInfo(recipecache,
                                    self.config_data,
                                    pn=actual_pn,
                                    fn=fn,
                                    fns=recipecache.pkg_pn[actual_pn])
        return recipe

    def parse_recipe(self, pn):
        """
        Parse the specified recipe and return a datastore object
        representing the environment for the recipe.
        """
        fn = self.get_recipe_file(pn)
        return self.parse_recipe_file(fn)

    def parse_recipe_file(self, fn, appends=True, appendlist=None, config_data=None):
        """
        Parse the specified recipe file (with or without bbappends)
        and return a datastore object representing the environment
        for the recipe.
        Parameters:
            fn: recipe file to parse - can be a file path or virtual
                specification
            appends: True to apply bbappends, False otherwise
            appendlist: optional list of bbappend files to apply, if you
                        want to filter them
            config_data: custom config datastore to use. NOTE: if you
                         specify config_data then you cannot use a virtual
                         specification for fn.
        """
        if self.tracking:
            # Enable history tracking just for the parse operation
            self.run_command('enableDataTracking')
        try:
            if appends and appendlist == []:
                appends = False
            if config_data:
                dctr = bb.remotedata.RemoteDatastores.transmit_datastore(config_data)
                dscon = self.run_command('parseRecipeFile', fn, appends, appendlist, dctr)
            else:
                dscon = self.run_command('parseRecipeFile', fn, appends, appendlist)
            if dscon:
                return self._reconvert_type(dscon, 'DataStoreConnectionHandle')
            else:
                return None
        finally:
            if self.tracking:
                self.run_command('disableDataTracking')

    def build_file(self, buildfile, task, internal=True):
        """
        Runs the specified task for just a single recipe (i.e. no dependencies).
        This is equivalent to bitbake -b, except with the default internal=True
        no warning about dependencies will be produced, normal info messages
        from the runqueue will be silenced and BuildInit, BuildStarted and
        BuildCompleted events will not be fired.
        """
        return self.run_command('buildFile', buildfile, task, internal)

    def build_targets(self, targets, task=None, handle_events=True, extra_events=None, event_callback=None):
        """
        Builds the specified targets. This is equivalent to a normal invocation
        of bitbake. Has built-in event handling which is enabled by default and
        can be extended if needed.
        Parameters:
            targets:
                One or more targets to build. Can be a list or a
                space-separated string.
            task:
                The task to run; if None then the value of BB_DEFAULT_TASK
                will be used. Default None.
            handle_events:
                True to handle events in a similar way to normal bitbake
                invocation with knotty; False to return immediately (on the
                assumption that the caller will handle the events instead).
                Default True.
            extra_events:
                An optional list of events to add to the event mask (if
                handle_events=True). If you add events here you also need
                to specify a callback function in event_callback that will
                handle the additional events. Default None.
            event_callback:
                An optional function taking a single parameter which
                will be called first upon receiving any event (if
                handle_events=True) so that the caller can override or
                extend the event handling. Default None.
        """
        if isinstance(targets, str):
            targets = targets.split()
        if not task:
            task = self.config_data.getVar('BB_DEFAULT_TASK')

        if handle_events:
            # A reasonable set of default events matching up with those we handle below
            eventmask = [
                        'bb.event.BuildStarted',
                        'bb.event.BuildCompleted',
                        'logging.LogRecord',
                        'bb.event.NoProvider',
                        'bb.command.CommandCompleted',
                        'bb.command.CommandFailed',
                        'bb.build.TaskStarted',
                        'bb.build.TaskFailed',
                        'bb.build.TaskSucceeded',
                        'bb.build.TaskFailedSilent',
                        'bb.build.TaskProgress',
                        'bb.runqueue.runQueueTaskStarted',
                        'bb.runqueue.sceneQueueTaskStarted',
                        'bb.event.ProcessStarted',
                        'bb.event.ProcessProgress',
                        'bb.event.ProcessFinished',
                        ]
            if extra_events:
                eventmask.extend(extra_events)
            ret = self.set_event_mask(eventmask)

        includelogs = self.config_data.getVar('BBINCLUDELOGS')
        loglines = self.config_data.getVar('BBINCLUDELOGS_LINES')

        ret = self.run_command('buildTargets', targets, task)
        if handle_events:
            result = False
            # Borrowed from knotty, instead somewhat hackily we use the helper
            # as the object to store "shutdown" on
            helper = bb.ui.uihelper.BBUIHelper()
            # We set up logging optionally in the constructor so now we need to
            # grab the handlers to pass to TerminalFilter
            console = None
            errconsole = None
            for handler in self.logger.handlers:
                if isinstance(handler, logging.StreamHandler):
                    if handler.stream == sys.stdout:
                        console = handler
                    elif handler.stream == sys.stderr:
                        errconsole = handler
            format_str = "%(levelname)s: %(message)s"
            format = bb.msg.BBLogFormatter(format_str)
            helper.shutdown = 0
            parseprogress = None
            termfilter = bb.ui.knotty.TerminalFilter(helper, helper, console, errconsole, format, quiet=self.quiet)
            try:
                while True:
                    try:
                        event = self.wait_event(0.25)
                        if event:
                            if event_callback and event_callback(event):
                                continue
                            if helper.eventHandler(event):
                                if isinstance(event, bb.build.TaskFailedSilent):
                                    logger.warning("Logfile for failed setscene task is %s" % event.logfile)
                                elif isinstance(event, bb.build.TaskFailed):
                                    bb.ui.knotty.print_event_log(event, includelogs, loglines, termfilter)
                                continue
                            if isinstance(event, bb.event.ProcessStarted):
                                if self.quiet > 1:
                                    continue
                                parseprogress = bb.ui.knotty.new_progress(event.processname, event.total)
                                parseprogress.start(False)
                                continue
                            if isinstance(event, bb.event.ProcessProgress):
                                if self.quiet > 1:
                                    continue
                                if parseprogress:
                                    parseprogress.update(event.progress)
                                else:
                                    bb.warn("Got ProcessProgress event for someting that never started?")
                                continue
                            if isinstance(event, bb.event.ProcessFinished):
                                if self.quiet > 1:
                                    continue
                                if parseprogress:
                                    parseprogress.finish()
                                parseprogress = None
                                continue
                            if isinstance(event, bb.command.CommandCompleted):
                                result = True
                                break
                            if isinstance(event, bb.command.CommandFailed):
                                self.logger.error(str(event))
                                result = False
                                break
                            if isinstance(event, logging.LogRecord):
                                if event.taskpid == 0 or event.levelno > logging.INFO:
                                    self.logger.handle(event)
                                continue
                            if isinstance(event, bb.event.NoProvider):
                                self.logger.error(str(event))
                                result = False
                                break

                        elif helper.shutdown > 1:
                            break
                        termfilter.updateFooter()
                    except KeyboardInterrupt:
                        termfilter.clearFooter()
                        if helper.shutdown == 1:
                            print("\nSecond Keyboard Interrupt, stopping...\n")
                            ret = self.run_command("stateForceShutdown")
                            if ret and ret[2]:
                                self.logger.error("Unable to cleanly stop: %s" % ret[2])
                        elif helper.shutdown == 0:
                            print("\nKeyboard Interrupt, closing down...\n")
                            interrupted = True
                            ret = self.run_command("stateShutdown")
                            if ret and ret[2]:
                                self.logger.error("Unable to cleanly shutdown: %s" % ret[2])
                        helper.shutdown = helper.shutdown + 1
                termfilter.clearFooter()
            finally:
                termfilter.finish()
            if helper.failed_tasks:
                result = False
            return result
        else:
            return ret

    def shutdown(self):
        """
        Shut down tinfoil. Disconnects from the server and gracefully
        releases any associated resources. You must call this function if
        prepare() has been called, or use a with... block when you create
        the tinfoil object which will ensure that it gets called.
        """
        if self.server_connection:
            self.run_command('clientComplete')
            _server_connections.remove(self.server_connection)
            bb.event.ui_queue = []
            self.server_connection.terminate()
            self.server_connection = None

        # Restore logging handlers to how it looked when we started
        if self.oldhandlers:
            for handler in self.logger.handlers:
                if handler not in self.oldhandlers:
                    self.logger.handlers.remove(handler)

    def _reconvert_type(self, obj, origtypename):
        """
        Convert an object back to the right type, in the case
        that marshalling has changed it (especially with xmlrpc)
        """
        supported_types = {
            'set': set,
            'DataStoreConnectionHandle': bb.command.DataStoreConnectionHandle,
        }

        origtype = supported_types.get(origtypename, None)
        if origtype is None:
            raise Exception('Unsupported type "%s"' % origtypename)
        if type(obj) == origtype:
            newobj = obj
        elif isinstance(obj, dict):
            # New style class
            newobj = origtype()
            for k,v in obj.items():
                setattr(newobj, k, v)
        else:
            # Assume we can coerce the type
            newobj = origtype(obj)

        if isinstance(newobj, bb.command.DataStoreConnectionHandle):
            connector = TinfoilDataStoreConnector(self, newobj.dsindex)
            newobj = bb.data.init()
            newobj.setVar('_remote_data', connector)

        return newobj


class TinfoilConfigParameters(BitBakeConfigParameters):

    def __init__(self, config_only, **options):
        self.initial_options = options
        # Apply some sane defaults
        if not 'parse_only' in options:
            self.initial_options['parse_only'] = not config_only
        #if not 'status_only' in options:
        #    self.initial_options['status_only'] = config_only
        if not 'ui' in options:
            self.initial_options['ui'] = 'knotty'
        if not 'argv' in options:
            self.initial_options['argv'] = []

        super(TinfoilConfigParameters, self).__init__()

    def parseCommandLine(self, argv=None):
        # We don't want any parameters parsed from the command line
        opts = super(TinfoilConfigParameters, self).parseCommandLine([])
        for key, val in self.initial_options.items():
            setattr(opts[0], key, val)
        return opts
