import collections
import fnmatch
import logging
import sys
import os
import re

import bb.utils

from bblayers.common import LayerPlugin

logger = logging.getLogger('bitbake-layers')


def plugin_init(plugins):
    return QueryPlugin()


class QueryPlugin(LayerPlugin):
    def do_show_layers(self, args):
        """show current configured layers."""
        logger.plain("%s  %s  %s" % ("layer".ljust(20), "path".ljust(40), "priority"))
        logger.plain('=' * 74)
        for layer, _, regex, pri in self.tinfoil.cooker.bbfile_config_priorities:
            layerdir = self.bbfile_collections.get(layer, None)
            layername = self.get_layer_name(layerdir)
            logger.plain("%s  %s  %d" % (layername.ljust(20), layerdir.ljust(40), pri))

    def version_str(self, pe, pv, pr = None):
        verstr = "%s" % pv
        if pr:
            verstr = "%s-%s" % (verstr, pr)
        if pe:
            verstr = "%s:%s" % (pe, verstr)
        return verstr

    def do_show_overlayed(self, args):
        """list overlayed recipes (where the same recipe exists in another layer)

Lists the names of overlayed recipes and the available versions in each
layer, with the preferred version first. Note that skipped recipes that
are overlayed will also be listed, with a " (skipped)" suffix.
"""

        items_listed = self.list_recipes('Overlayed recipes', None, True, args.same_version, args.filenames, True, None)

        # Check for overlayed .bbclass files
        classes = collections.defaultdict(list)
        for layerdir in self.bblayers:
            classdir = os.path.join(layerdir, 'classes')
            if os.path.exists(classdir):
                for classfile in os.listdir(classdir):
                    if os.path.splitext(classfile)[1] == '.bbclass':
                        classes[classfile].append(classdir)

        # Locating classes and other files is a bit more complicated than recipes -
        # layer priority is not a factor; instead BitBake uses the first matching
        # file in BBPATH, which is manipulated directly by each layer's
        # conf/layer.conf in turn, thus the order of layers in bblayers.conf is a
        # factor - however, each layer.conf is free to either prepend or append to
        # BBPATH (or indeed do crazy stuff with it). Thus the order in BBPATH might
        # not be exactly the order present in bblayers.conf either.
        bbpath = str(self.tinfoil.config_data.getVar('BBPATH'))
        overlayed_class_found = False
        for (classfile, classdirs) in classes.items():
            if len(classdirs) > 1:
                if not overlayed_class_found:
                    logger.plain('=== Overlayed classes ===')
                    overlayed_class_found = True

                mainfile = bb.utils.which(bbpath, os.path.join('classes', classfile))
                if args.filenames:
                    logger.plain('%s' % mainfile)
                else:
                    # We effectively have to guess the layer here
                    logger.plain('%s:' % classfile)
                    mainlayername = '?'
                    for layerdir in self.bblayers:
                        classdir = os.path.join(layerdir, 'classes')
                        if mainfile.startswith(classdir):
                            mainlayername = self.get_layer_name(layerdir)
                    logger.plain('  %s' % mainlayername)
                for classdir in classdirs:
                    fullpath = os.path.join(classdir, classfile)
                    if fullpath != mainfile:
                        if args.filenames:
                            print('  %s' % fullpath)
                        else:
                            print('  %s' % self.get_layer_name(os.path.dirname(classdir)))

        if overlayed_class_found:
            items_listed = True;

        if not items_listed:
            logger.plain('No overlayed files found.')

    def do_show_recipes(self, args):
        """list available recipes, showing the layer they are provided by

Lists the names of recipes and the available versions in each
layer, with the preferred version first. Optionally you may specify
pnspec to match a specified recipe name (supports wildcards). Note that
skipped recipes will also be listed, with a " (skipped)" suffix.
"""

        inheritlist = args.inherits.split(',') if args.inherits else []
        if inheritlist or args.pnspec or args.multiple:
            title = 'Matching recipes:'
        else:
            title = 'Available recipes:'
        self.list_recipes(title, args.pnspec, False, False, args.filenames, args.multiple, inheritlist)

    def list_recipes(self, title, pnspec, show_overlayed_only, show_same_ver_only, show_filenames, show_multi_provider_only, inherits):
        if inherits:
            bbpath = str(self.tinfoil.config_data.getVar('BBPATH'))
            for classname in inherits:
                classfile = 'classes/%s.bbclass' % classname
                if not bb.utils.which(bbpath, classfile, history=False):
                    logger.error('No class named %s found in BBPATH', classfile)
                    sys.exit(1)

        pkg_pn = self.tinfoil.cooker.recipecaches[''].pkg_pn
        (latest_versions, preferred_versions) = self.tinfoil.find_providers()
        allproviders = self.tinfoil.get_all_providers()

        # Ensure we list skipped recipes
        # We are largely guessing about PN, PV and the preferred version here,
        # but we have no choice since skipped recipes are not fully parsed
        skiplist = list(self.tinfoil.cooker.skiplist.keys())
        for fn in skiplist:
            recipe_parts = os.path.splitext(os.path.basename(fn))[0].split('_')
            p = recipe_parts[0]
            if len(recipe_parts) > 1:
                ver = (None, recipe_parts[1], None)
            else:
                ver = (None, 'unknown', None)
            allproviders[p].append((ver, fn))
            if not p in pkg_pn:
                pkg_pn[p] = 'dummy'
                preferred_versions[p] = (ver, fn)

        def print_item(f, pn, ver, layer, ispref):
            if f in skiplist:
                skipped = ' (skipped)'
            else:
                skipped = ''
            if show_filenames:
                if ispref:
                    logger.plain("%s%s", f, skipped)
                else:
                    logger.plain("  %s%s", f, skipped)
            else:
                if ispref:
                    logger.plain("%s:", pn)
                logger.plain("  %s %s%s", layer.ljust(20), ver, skipped)

        global_inherit = (self.tinfoil.config_data.getVar('INHERIT') or "").split()
        cls_re = re.compile('classes/')

        preffiles = []
        items_listed = False
        for p in sorted(pkg_pn):
            if pnspec:
                found=False
                for pnm in pnspec:
                    if fnmatch.fnmatch(p, pnm):
                        found=True
                        break
                if not found:
                    continue

            if len(allproviders[p]) > 1 or not show_multi_provider_only:
                pref = preferred_versions[p]
                realfn = bb.cache.virtualfn2realfn(pref[1])
                preffile = realfn[0]

                # We only display once per recipe, we should prefer non extended versions of the
                # recipe if present (so e.g. in OpenEmbedded, openssl rather than nativesdk-openssl
                # which would otherwise sort first).
                if realfn[1] and realfn[0] in self.tinfoil.cooker.recipecaches[''].pkg_fn:
                    continue

                if inherits:
                    matchcount = 0
                    recipe_inherits = self.tinfoil.cooker_data.inherits.get(preffile, [])
                    for cls in recipe_inherits:
                        if cls_re.match(cls):
                            continue
                        classname = os.path.splitext(os.path.basename(cls))[0]
                        if classname in global_inherit:
                            continue
                        elif classname in inherits:
                            matchcount += 1
                    if matchcount != len(inherits):
                        # No match - skip this recipe
                        continue

                if preffile not in preffiles:
                    preflayer = self.get_file_layer(preffile)
                    multilayer = False
                    same_ver = True
                    provs = []
                    for prov in allproviders[p]:
                        provfile = bb.cache.virtualfn2realfn(prov[1])[0]
                        provlayer = self.get_file_layer(provfile)
                        provs.append((provfile, provlayer, prov[0]))
                        if provlayer != preflayer:
                            multilayer = True
                        if prov[0] != pref[0]:
                            same_ver = False

                    if (multilayer or not show_overlayed_only) and (same_ver or not show_same_ver_only):
                        if not items_listed:
                            logger.plain('=== %s ===' % title)
                            items_listed = True
                        print_item(preffile, p, self.version_str(pref[0][0], pref[0][1]), preflayer, True)
                        for (provfile, provlayer, provver) in provs:
                            if provfile != preffile:
                                print_item(provfile, p, self.version_str(provver[0], provver[1]), provlayer, False)
                        # Ensure we don't show two entries for BBCLASSEXTENDed recipes
                        preffiles.append(preffile)

        return items_listed

    def get_file_layer(self, filename):
        layerdir = self.get_file_layerdir(filename)
        if layerdir:
            return self.get_layer_name(layerdir)
        else:
            return '?'

    def get_file_layerdir(self, filename):
        layer = bb.utils.get_file_layer(filename, self.tinfoil.config_data)
        return self.bbfile_collections.get(layer, None)

    def remove_layer_prefix(self, f):
        """Remove the layer_dir prefix, e.g., f = /path/to/layer_dir/foo/blah, the
           return value will be: layer_dir/foo/blah"""
        f_layerdir = self.get_file_layerdir(f)
        if not f_layerdir:
            return f
        prefix = os.path.join(os.path.dirname(f_layerdir), '')
        return f[len(prefix):] if f.startswith(prefix) else f

    def do_show_appends(self, args):
        """list bbappend files and recipe files they apply to

Lists recipes with the bbappends that apply to them as subitems.
"""
        if args.pnspec:
            logger.plain('=== Matched appended recipes ===')
        else:
            logger.plain('=== Appended recipes ===')

        pnlist = list(self.tinfoil.cooker_data.pkg_pn.keys())
        pnlist.sort()
        appends = False
        for pn in pnlist:
            if args.pnspec:
                found=False
                for pnm in args.pnspec:
                    if fnmatch.fnmatch(pn, pnm):
                        found=True
                        break
                if not found:
                    continue

            if self.show_appends_for_pn(pn):
                appends = True

        if not args.pnspec and self.show_appends_for_skipped():
            appends = True

        if not appends:
            logger.plain('No append files found')

    def show_appends_for_pn(self, pn):
        filenames = self.tinfoil.cooker_data.pkg_pn[pn]

        best = self.tinfoil.find_best_provider(pn)
        best_filename = os.path.basename(best[3])

        return self.show_appends_output(filenames, best_filename)

    def show_appends_for_skipped(self):
        filenames = [os.path.basename(f)
                    for f in self.tinfoil.cooker.skiplist.keys()]
        return self.show_appends_output(filenames, None, " (skipped)")

    def show_appends_output(self, filenames, best_filename, name_suffix = ''):
        appended, missing = self.get_appends_for_files(filenames)
        if appended:
            for basename, appends in appended:
                logger.plain('%s%s:', basename, name_suffix)
                for append in appends:
                    logger.plain('  %s', append)

            if best_filename:
                if best_filename in missing:
                    logger.warning('%s: missing append for preferred version',
                                   best_filename)
            return True
        else:
            return False

    def get_appends_for_files(self, filenames):
        appended, notappended = [], []
        for filename in filenames:
            _, cls, _ = bb.cache.virtualfn2realfn(filename)
            if cls:
                continue

            basename = os.path.basename(filename)
            appends = self.tinfoil.cooker.collection.get_file_appends(basename)
            if appends:
                appended.append((basename, list(appends)))
            else:
                notappended.append(basename)
        return appended, notappended

    def do_show_cross_depends(self, args):
        """Show dependencies between recipes that cross layer boundaries.

Figure out the dependencies between recipes that cross layer boundaries.

NOTE: .bbappend files can impact the dependencies.
"""
        ignore_layers = (args.ignore or '').split(',')

        pkg_fn = self.tinfoil.cooker_data.pkg_fn
        bbpath = str(self.tinfoil.config_data.getVar('BBPATH'))
        self.require_re = re.compile(r"require\s+(.+)")
        self.include_re = re.compile(r"include\s+(.+)")
        self.inherit_re = re.compile(r"inherit\s+(.+)")

        global_inherit = (self.tinfoil.config_data.getVar('INHERIT') or "").split()

        # The bb's DEPENDS and RDEPENDS
        for f in pkg_fn:
            f = bb.cache.virtualfn2realfn(f)[0]
            # Get the layername that the file is in
            layername = self.get_file_layer(f)

            # The DEPENDS
            deps = self.tinfoil.cooker_data.deps[f]
            for pn in deps:
                if pn in self.tinfoil.cooker_data.pkg_pn:
                    best = self.tinfoil.find_best_provider(pn)
                    self.check_cross_depends("DEPENDS", layername, f, best[3], args.filenames, ignore_layers)

            # The RDPENDS
            all_rdeps = self.tinfoil.cooker_data.rundeps[f].values()
            # Remove the duplicated or null one.
            sorted_rdeps = {}
            # The all_rdeps is the list in list, so we need two for loops
            for k1 in all_rdeps:
                for k2 in k1:
                    sorted_rdeps[k2] = 1
            all_rdeps = sorted_rdeps.keys()
            for rdep in all_rdeps:
                all_p, best = self.tinfoil.get_runtime_providers(rdep)
                if all_p:
                    if f in all_p:
                        # The recipe provides this one itself, ignore
                        continue
                    self.check_cross_depends("RDEPENDS", layername, f, best, args.filenames, ignore_layers)

            # The RRECOMMENDS
            all_rrecs = self.tinfoil.cooker_data.runrecs[f].values()
            # Remove the duplicated or null one.
            sorted_rrecs = {}
            # The all_rrecs is the list in list, so we need two for loops
            for k1 in all_rrecs:
                for k2 in k1:
                    sorted_rrecs[k2] = 1
            all_rrecs = sorted_rrecs.keys()
            for rrec in all_rrecs:
                all_p, best = self.tinfoil.get_runtime_providers(rrec)
                if all_p:
                    if f in all_p:
                        # The recipe provides this one itself, ignore
                        continue
                    self.check_cross_depends("RRECOMMENDS", layername, f, best, args.filenames, ignore_layers)

            # The inherit class
            cls_re = re.compile('classes/')
            if f in self.tinfoil.cooker_data.inherits:
                inherits = self.tinfoil.cooker_data.inherits[f]
                for cls in inherits:
                    # The inherits' format is [classes/cls, /path/to/classes/cls]
                    # ignore the classes/cls.
                    if not cls_re.match(cls):
                        classname = os.path.splitext(os.path.basename(cls))[0]
                        if classname in global_inherit:
                            continue
                        inherit_layername = self.get_file_layer(cls)
                        if inherit_layername != layername and not inherit_layername in ignore_layers:
                            if not args.filenames:
                                f_short = self.remove_layer_prefix(f)
                                cls = self.remove_layer_prefix(cls)
                            else:
                                f_short = f
                            logger.plain("%s inherits %s" % (f_short, cls))

            # The 'require/include xxx' in the bb file
            pv_re = re.compile(r"\${PV}")
            with open(f, 'r') as fnfile:
                line = fnfile.readline()
                while line:
                    m, keyword = self.match_require_include(line)
                    # Found the 'require/include xxxx'
                    if m:
                        needed_file = m.group(1)
                        # Replace the ${PV} with the real PV
                        if pv_re.search(needed_file) and f in self.tinfoil.cooker_data.pkg_pepvpr:
                            pv = self.tinfoil.cooker_data.pkg_pepvpr[f][1]
                            needed_file = re.sub(r"\${PV}", pv, needed_file)
                        self.print_cross_files(bbpath, keyword, layername, f, needed_file, args.filenames, ignore_layers)
                    line = fnfile.readline()

        # The "require/include xxx" in conf/machine/*.conf, .inc and .bbclass
        conf_re = re.compile(".*/conf/machine/[^\/]*\.conf$")
        inc_re = re.compile(".*\.inc$")
        # The "inherit xxx" in .bbclass
        bbclass_re = re.compile(".*\.bbclass$")
        for layerdir in self.bblayers:
            layername = self.get_layer_name(layerdir)
            for dirpath, dirnames, filenames in os.walk(layerdir):
                for name in filenames:
                    f = os.path.join(dirpath, name)
                    s = conf_re.match(f) or inc_re.match(f) or bbclass_re.match(f)
                    if s:
                        with open(f, 'r') as ffile:
                            line = ffile.readline()
                            while line:
                                m, keyword = self.match_require_include(line)
                                # Only bbclass has the "inherit xxx" here.
                                bbclass=""
                                if not m and f.endswith(".bbclass"):
                                    m, keyword = self.match_inherit(line)
                                    bbclass=".bbclass"
                                # Find a 'require/include xxxx'
                                if m:
                                    self.print_cross_files(bbpath, keyword, layername, f, m.group(1) + bbclass, args.filenames, ignore_layers)
                                line = ffile.readline()

    def print_cross_files(self, bbpath, keyword, layername, f, needed_filename, show_filenames, ignore_layers):
        """Print the depends that crosses a layer boundary"""
        needed_file = bb.utils.which(bbpath, needed_filename)
        if needed_file:
            # Which layer is this file from
            needed_layername = self.get_file_layer(needed_file)
            if needed_layername != layername and not needed_layername in ignore_layers:
                if not show_filenames:
                    f = self.remove_layer_prefix(f)
                    needed_file = self.remove_layer_prefix(needed_file)
                logger.plain("%s %s %s" %(f, keyword, needed_file))

    def match_inherit(self, line):
        """Match the inherit xxx line"""
        return (self.inherit_re.match(line), "inherits")

    def match_require_include(self, line):
        """Match the require/include xxx line"""
        m = self.require_re.match(line)
        keyword = "requires"
        if not m:
            m = self.include_re.match(line)
            keyword = "includes"
        return (m, keyword)

    def check_cross_depends(self, keyword, layername, f, needed_file, show_filenames, ignore_layers):
        """Print the DEPENDS/RDEPENDS file that crosses a layer boundary"""
        best_realfn = bb.cache.virtualfn2realfn(needed_file)[0]
        needed_layername = self.get_file_layer(best_realfn)
        if needed_layername != layername and not needed_layername in ignore_layers:
            if not show_filenames:
                f = self.remove_layer_prefix(f)
                best_realfn = self.remove_layer_prefix(best_realfn)

            logger.plain("%s %s %s" % (f, keyword, best_realfn))

    def register_commands(self, sp):
        self.add_command(sp, 'show-layers', self.do_show_layers, parserecipes=False)

        parser_show_overlayed = self.add_command(sp, 'show-overlayed', self.do_show_overlayed)
        parser_show_overlayed.add_argument('-f', '--filenames', help='instead of the default formatting, list filenames of higher priority recipes with the ones they overlay indented underneath', action='store_true')
        parser_show_overlayed.add_argument('-s', '--same-version', help='only list overlayed recipes where the version is the same', action='store_true')

        parser_show_recipes = self.add_command(sp, 'show-recipes', self.do_show_recipes)
        parser_show_recipes.add_argument('-f', '--filenames', help='instead of the default formatting, list filenames of higher priority recipes with the ones they overlay indented underneath', action='store_true')
        parser_show_recipes.add_argument('-m', '--multiple', help='only list where multiple recipes (in the same layer or different layers) exist for the same recipe name', action='store_true')
        parser_show_recipes.add_argument('-i', '--inherits', help='only list recipes that inherit the named class(es) - separate multiple classes using , (without spaces)', metavar='CLASS', default='')
        parser_show_recipes.add_argument('pnspec', nargs='*', help='optional recipe name specification (wildcards allowed, enclose in quotes to avoid shell expansion)')

        parser_show_appends = self.add_command(sp, 'show-appends', self.do_show_appends)
        parser_show_appends.add_argument('pnspec', nargs='*', help='optional recipe name specification (wildcards allowed, enclose in quotes to avoid shell expansion)')

        parser_show_cross_depends = self.add_command(sp, 'show-cross-depends', self.do_show_cross_depends)
        parser_show_cross_depends.add_argument('-f', '--filenames', help='show full file path', action='store_true')
        parser_show_cross_depends.add_argument('-i', '--ignore', help='ignore dependencies on items in the specified layer(s) (split multiple layer names with commas, no spaces)', metavar='LAYERNAME')
