# In order to support a deterministic set of 'dynamic' users/groups,
# we need a function to reformat the params based on a static file
def update_useradd_static_config(d):
    import itertools
    import re
    import errno
    import oe.useradd

    def list_extend(iterable, length, obj = None):
        """Ensure that iterable is the specified length by extending with obj
        and return it as a list"""
        return list(itertools.islice(itertools.chain(iterable, itertools.repeat(obj)), length))

    def merge_files(file_list, exp_fields):
        """Read each passwd/group file in file_list, split each line and create
        a dictionary with the user/group names as keys and the split lines as
        values. If the user/group name already exists in the dictionary, then
        update any fields in the list with the values from the new list (if they
        are set)."""
        id_table = dict()
        for conf in file_list.split():
            try:
                with open(conf, "r") as f:
                    for line in f:
                        if line.startswith('#'):
                            continue
                        # Make sure there always are at least exp_fields
                        # elements in the field list. This allows for leaving
                        # out trailing colons in the files.
                        fields = list_extend(line.rstrip().split(":"), exp_fields)
                        if fields[0] not in id_table:
                            id_table[fields[0]] = fields
                        else:
                            id_table[fields[0]] = list(map(lambda x, y: x or y, fields, id_table[fields[0]]))
            except IOError as e:
                if e.errno == errno.ENOENT:
                    pass

        return id_table

    def handle_missing_id(id, type, pkg, files, var, value):
        # For backwards compatibility we accept "1" in addition to "error"
        error_dynamic = d.getVar('USERADD_ERROR_DYNAMIC')
        msg = "%s - %s: %sname %s does not have a static ID defined." % (d.getVar('PN'), pkg, type, id)
        if files:
            msg += " Add %s to one of these files: %s" % (id, files)
        else:
            msg += " %s file(s) not found in BBPATH: %s" % (var, value)
        if error_dynamic == 'error' or error_dynamic == '1':
            raise NotImplementedError(msg)
        elif error_dynamic == 'warn':
            bb.warn(msg)
        elif error_dynamic == 'skip':
            raise bb.parse.SkipRecipe(msg)

    # Return a list of configuration files based on either the default
    # files/group or the contents of USERADD_GID_TABLES, resp.
    # files/passwd for USERADD_UID_TABLES.
    # Paths are resolved via BBPATH.
    def get_table_list(d, var, default):
        files = []
        bbpath = d.getVar('BBPATH')
        tables = d.getVar(var)
        if not tables:
            tables = default
        for conf_file in tables.split():
            files.append(bb.utils.which(bbpath, conf_file))
        return (' '.join(files), var, default)

    # We parse and rewrite the useradd components
    def rewrite_useradd(params, is_pkg):
        parser = oe.useradd.build_useradd_parser()

        newparams = []
        users = None
        for param in oe.useradd.split_commands(params):
            try:
                uaargs = parser.parse_args(oe.useradd.split_args(param))
            except Exception as e:
                bb.fatal("%s: Unable to parse arguments for USERADD_PARAM:%s '%s': %s" % (d.getVar('PN'), pkg, param, e))

            # Read all passwd files specified in USERADD_UID_TABLES or files/passwd
            # Use the standard passwd layout:
            #  username:password:user_id:group_id:comment:home_directory:login_shell
            #
            # If a field is left blank, the original value will be used.  The 'username'
            # field is required.
            #
            # Note: we ignore the password field, as including even the hashed password
            # in the useradd command may introduce a security hole.  It's assumed that
            # all new users get the default ('*' which prevents login) until the user is
            # specifically configured by the system admin.
            if not users:
                files, table_var, table_value = get_table_list(d, 'USERADD_UID_TABLES', 'files/passwd')
                users = merge_files(files, 7)

            type = 'system user' if uaargs.system else 'normal user'
            if uaargs.LOGIN not in users:
                handle_missing_id(uaargs.LOGIN, type, pkg, files, table_var, table_value)
                newparams.append(param)
                continue

            field = users[uaargs.LOGIN]

            if uaargs.uid and field[2] and (uaargs.uid != field[2]):
                bb.warn("%s: Changing username %s's uid from (%s) to (%s), verify configuration files!" % (d.getVar('PN'), uaargs.LOGIN, uaargs.uid, field[2]))
            uaargs.uid = field[2] or uaargs.uid

            # Determine the possible groupname
            # Unless the group name (or gid) is specified, we assume that the LOGIN is the groupname
            #
            # By default the system has creation of the matching groups enabled
            # So if the implicit username-group creation is on, then the implicit groupname (LOGIN)
            # is used, and we disable the user_group option.
            #
            if uaargs.gid:
                uaargs.groupname = uaargs.gid
            elif uaargs.user_group is not False:
                uaargs.groupname = uaargs.LOGIN
            else:
                uaargs.groupname = 'users'
            uaargs.groupid = field[3] or uaargs.groupname

            if uaargs.groupid and uaargs.gid != uaargs.groupid:
                newgroup = None
                if not uaargs.groupid.isdigit():
                    # We don't have a group number, so we have to add a name
                    bb.debug(1, "Adding group %s!" % uaargs.groupid)
                    newgroup = "%s %s" % (' --system' if uaargs.system else '', uaargs.groupid)
                elif uaargs.groupname and not uaargs.groupname.isdigit():
                    # We have a group name and a group number to assign it to
                    bb.debug(1, "Adding group %s (gid %s)!" % (uaargs.groupname, uaargs.groupid))
                    newgroup = "-g %s %s" % (uaargs.groupid, uaargs.groupname)
                else:
                    # We want to add a group, but we don't know it's name... so we can't add the group...
                    # We have to assume the group has previously been added or we'll fail on the adduser...
                    # Note: specifying the actual gid is very rare in OE, usually the group name is specified.
                    bb.warn("%s: Changing gid for login %s to %s, verify configuration files!" % (d.getVar('PN'), uaargs.LOGIN, uaargs.groupid))

                uaargs.gid = uaargs.groupid
                uaargs.user_group = None
                if newgroup and is_pkg:
                    groupadd = d.getVar("GROUPADD_PARAM:%s" % pkg)
                    if groupadd:
                        # Only add the group if not already specified
                        if not uaargs.groupname in groupadd:
                            d.setVar("GROUPADD_PARAM:%s" % pkg, "%s; %s" % (groupadd, newgroup))
                    else:
                        d.setVar("GROUPADD_PARAM:%s" % pkg, newgroup)

            uaargs.comment = "'%s'" % field[4] if field[4] else uaargs.comment
            uaargs.home_dir = field[5] or uaargs.home_dir
            uaargs.shell = field[6] or uaargs.shell

            # Should be an error if a specific option is set...
            if not uaargs.uid or not uaargs.uid.isdigit() or not uaargs.gid:
                 handle_missing_id(uaargs.LOGIN, type, pkg, files, table_var, table_value)

            # Reconstruct the args...
            newparam  = ['', ' --defaults'][uaargs.defaults]
            newparam += ['', ' --base-dir %s' % uaargs.base_dir][uaargs.base_dir != None]
            newparam += ['', ' --comment %s' % uaargs.comment][uaargs.comment != None]
            newparam += ['', ' --home-dir %s' % uaargs.home_dir][uaargs.home_dir != None]
            newparam += ['', ' --expiredate %s' % uaargs.expiredate][uaargs.expiredate != None]
            newparam += ['', ' --inactive %s' % uaargs.inactive][uaargs.inactive != None]
            newparam += ['', ' --gid %s' % uaargs.gid][uaargs.gid != None]
            newparam += ['', ' --groups %s' % uaargs.groups][uaargs.groups != None]
            newparam += ['', ' --skel %s' % uaargs.skel][uaargs.skel != None]
            newparam += ['', ' --key %s' % uaargs.key][uaargs.key != None]
            newparam += ['', ' --no-log-init'][uaargs.no_log_init]
            newparam += ['', ' --create-home'][uaargs.create_home is True]
            newparam += ['', ' --no-create-home'][uaargs.create_home is False]
            newparam += ['', ' --no-user-group'][uaargs.user_group is False]
            newparam += ['', ' --non-unique'][uaargs.non_unique]
            if uaargs.password != None:
                newparam += ['', ' --password %s' % uaargs.password][uaargs.password != None]
            newparam += ['', ' --root %s' % uaargs.root][uaargs.root != None]
            newparam += ['', ' --system'][uaargs.system]
            newparam += ['', ' --shell %s' % uaargs.shell][uaargs.shell != None]
            newparam += ['', ' --uid %s' % uaargs.uid][uaargs.uid != None]
            newparam += ['', ' --user-group'][uaargs.user_group is True]
            newparam += ' %s' % uaargs.LOGIN

            newparams.append(newparam)

        return ";".join(newparams).strip()

    # We parse and rewrite the groupadd components
    def rewrite_groupadd(params, is_pkg):
        parser = oe.useradd.build_groupadd_parser()

        newparams = []
        groups = None
        for param in oe.useradd.split_commands(params):
            try:
                # If we're processing multiple lines, we could have left over values here...
                gaargs = parser.parse_args(oe.useradd.split_args(param))
            except Exception as e:
                bb.fatal("%s: Unable to parse arguments for GROUPADD_PARAM:%s '%s': %s" % (d.getVar('PN'), pkg, param, e))

            # Read all group files specified in USERADD_GID_TABLES or files/group
            # Use the standard group layout:
            #  groupname:password:group_id:group_members
            #
            # If a field is left blank, the original value will be used. The 'groupname' field
            # is required.
            #
            # Note: similar to the passwd file, the 'password' filed is ignored
            # Note: group_members is ignored, group members must be configured with the GROUPMEMS_PARAM
            if not groups:
                files, table_var, table_value = get_table_list(d, 'USERADD_GID_TABLES', 'files/group')
                groups = merge_files(files, 4)

            type = 'system group' if gaargs.system else 'normal group'
            if gaargs.GROUP not in groups:
                handle_missing_id(gaargs.GROUP, type, pkg, files, table_var, table_value)
                newparams.append(param)
                continue

            field = groups[gaargs.GROUP]

            if field[2]:
                if gaargs.gid and (gaargs.gid != field[2]):
                    bb.warn("%s: Changing groupname %s's gid from (%s) to (%s), verify configuration files!" % (d.getVar('PN'), gaargs.GROUP, gaargs.gid, field[2]))
                gaargs.gid = field[2]

            if not gaargs.gid or not gaargs.gid.isdigit():
                handle_missing_id(gaargs.GROUP, type, pkg, files, table_var, table_value)

            # Reconstruct the args...
            newparam  = ['', ' --force'][gaargs.force]
            newparam += ['', ' --gid %s' % gaargs.gid][gaargs.gid != None]
            newparam += ['', ' --key %s' % gaargs.key][gaargs.key != None]
            newparam += ['', ' --non-unique'][gaargs.non_unique]
            if gaargs.password != None:
                newparam += ['', ' --password %s' % gaargs.password][gaargs.password != None]
            newparam += ['', ' --root %s' % gaargs.root][gaargs.root != None]
            newparam += ['', ' --system'][gaargs.system]
            newparam += ' %s' % gaargs.GROUP

            newparams.append(newparam)

        return ";".join(newparams).strip()

    # The parsing of the current recipe depends on the content of
    # the files listed in USERADD_UID/GID_TABLES. We need to tell bitbake
    # about that explicitly to trigger re-parsing and thus re-execution of
    # this code when the files change.
    bbpath = d.getVar('BBPATH')
    for varname, default in (('USERADD_UID_TABLES', 'files/passwd'),
                             ('USERADD_GID_TABLES', 'files/group')):
        tables = d.getVar(varname)
        if not tables:
            tables = default
        for conf_file in tables.split():
            bb.parse.mark_dependency(d, bb.utils.which(bbpath, conf_file))

    # Load and process the users and groups, rewriting the adduser/addgroup params
    useradd_packages = d.getVar('USERADD_PACKAGES') or ""

    for pkg in useradd_packages.split():
        # Groupmems doesn't have anything we might want to change, so simply validating
        # is a bit of a waste -- only process useradd/groupadd
        useradd_param = d.getVar('USERADD_PARAM:%s' % pkg)
        if useradd_param:
            #bb.warn("Before: 'USERADD_PARAM:%s' - '%s'" % (pkg, useradd_param))
            d.setVar('USERADD_PARAM:%s' % pkg, rewrite_useradd(useradd_param, True))
            #bb.warn("After:  'USERADD_PARAM:%s' - '%s'" % (pkg, d.getVar('USERADD_PARAM:%s' % pkg)))

        groupadd_param = d.getVar('GROUPADD_PARAM:%s' % pkg)
        if groupadd_param:
            #bb.warn("Before: 'GROUPADD_PARAM:%s' - '%s'" % (pkg, groupadd_param))
            d.setVar('GROUPADD_PARAM:%s' % pkg, rewrite_groupadd(groupadd_param, True))
            #bb.warn("After:  'GROUPADD_PARAM:%s' - '%s'" % (pkg, d.getVar('GROUPADD_PARAM:%s' % pkg)))

    # Load and process extra users and groups, rewriting only adduser/addgroup params
    pkg = d.getVar('PN')
    extrausers = d.getVar('EXTRA_USERS_PARAMS') or ""

    #bb.warn("Before:  'EXTRA_USERS_PARAMS' - '%s'" % (d.getVar('EXTRA_USERS_PARAMS')))
    new_extrausers = []
    for cmd in oe.useradd.split_commands(extrausers):
        if re.match('''useradd (.*)''', cmd):
            useradd_param = re.match('''useradd (.*)''', cmd).group(1)
            useradd_param = rewrite_useradd(useradd_param, False)
            cmd = 'useradd %s' % useradd_param
        elif re.match('''groupadd (.*)''', cmd):
            groupadd_param = re.match('''groupadd (.*)''', cmd).group(1)
            groupadd_param = rewrite_groupadd(groupadd_param, False)
            cmd = 'groupadd %s' % groupadd_param

        new_extrausers.append(cmd)

    new_extrausers.append('')
    d.setVar('EXTRA_USERS_PARAMS', ';'.join(new_extrausers))
    #bb.warn("After:  'EXTRA_USERS_PARAMS' - '%s'" % (d.getVar('EXTRA_USERS_PARAMS')))


python __anonymous() {
    if not bb.data.inherits_class('nativesdk', d) \
        and not bb.data.inherits_class('native', d):
        try:
            update_useradd_static_config(d)
        except NotImplementedError as f:
            bb.debug(1, "Skipping recipe %s: %s" % (d.getVar('PN'), f))
            raise bb.parse.SkipRecipe(f)
}
