#! /usr/bin/env python3

def read_file(path: str) -> "List of lines":
    # File-Objekt ist gleichzeitig Context-Manager,
    #    schliesst beim Verlassen des Kontextes automatisch den File-Deskriptor
    with open(path, 'r') as f:
        # f.read(buflen) - binary read
        # f.readline()   - 1 Textzeile lesen -> str
        # f.readlines()  - alle Textzeilen lesen -> list
        # f ist gleichzeitig Iterator
    
        # 1. Variante: explizite for-Schleife
        lines = []
        for line in f.readlines():
            lines.append(line.rstrip())
    
        # 2. Variante: Mit Hilfe von Lambda und f als Iterator
        #lines = list(map(lambda s: s.rstrip(), f))
    
        # 3. Variante: Klassenfunktion rstrip und f als Iterator
        #lines = list(map(str.rstrip, f))
    
        # 4. Variante: Mit List Comprehension und f als Iterator
        #lines = [line.rstrip() for line in f]

    return lines


def parse_passwd_line(line: str) -> "Dict of passwd details":
    parts = line.split(':') # erzeugt List of Strings

    # userdict = {'username': parts[0], ...}
    # https://de.wikipedia.org/wiki/GECOS-Feld
    userdict = dict(username=parts[0],
                    uid=int(parts[2]),
                    gid=int(parts[3]),
                    realname=parts[4].split(',')[0],
                    gecos=parts[4],
                    home=parts[5],
                    shell=parts[6])

    return userdict


def build_userlist(lines) -> "List of user dicts":
    result = []

    for line in lines:
        result.append(parse_passwd_line(line))

    return result

def print_userlist_sorted_by_username(userlist):
    # Sorted iteriert ueber die userlist und
    #   ruft fuer jedes Element key(elem) auf
    #   also e im Lambda-Ausdruck ist Element der Liste (also der Userdict)
    # Sorted baut Shadow-Liste mit Sortierkriterien auf
    for user in sorted(userlist, key=lambda e: e['username'].lower()):
        print(user['username'], user['uid'], user['realname'])


def print_userlist_sorted_by_uid(userlist):
    userlen = max(map(lambda u: len(u['username']), userlist))

    for user in sorted(userlist, key=lambda e: e['uid']):
        print("{uid:5} {username:{width}} {realname}".format(width=userlen, **user))


def main():
    # Dictionary mit Ausgabe-Funktionen als Referenz
    output_functions = {
                        'username': print_userlist_sorted_by_username,
                        'uid': print_userlist_sorted_by_uid,
                       }
    # Zum Test diese spezielle Ausgabe-Funktion verwenden
    # 'username' kommt spaeter von der Kommandozeile
    # outfunc = output_functions['username']
    outfunc = output_functions['uid']

    lines = read_file("/etc/passwd")
    userlist = build_userlist(lines)
    # print(userlist) # Kontrollausgabe
    outfunc(userlist)


main()
