#!/usr/bin/env python3

import argparse
from jinja2 import Template, Environment, FileSystemLoader
import pathlib


def main():
    parser = argparse.ArgumentParser(description='basic Gentoo PAM configuration files')
    parser.add_argument('--gnome-keyring', action="store_true", help='enable pam_gnome_keyring.so module')
    parser.add_argument('--caps', action="store_true", help='enable pam_cap.so module')
    parser.add_argument('--passwdqc', action="store_true", help='enable pam_passwdqc.so module')
    parser.add_argument('--pwhistory', action="store_true", help='enable pam_pwhistory.so module')
    parser.add_argument('--pwquality', action="store_true", help='enable pam_pwquality.so module')
    parser.add_argument('--elogind', action="store_true", help='enable pam_elogind.so module')
    parser.add_argument('--systemd', action="store_true", help='enable pam_systemd.so module')
    parser.add_argument('--homed', action="store_true", help='enable pam_systemd_home.so module')
    parser.add_argument('--selinux', action="store_true", help='enable pam_selinux.so module')
    parser.add_argument('--mktemp', action="store_true", help='enable pam_mktemp.so module')
    parser.add_argument('--pam-ssh', action="store_true", help='enable pam_ssh.so module')
    parser.add_argument('--securetty', action="store_true", help='enable pam_securetty.so module')
    parser.add_argument('--sssd', action="store_true", help='enable sssd.so module')
    parser.add_argument('--yescrypt', action="store_true", help='enable yescrypt option for pam_unix.so module')
    parser.add_argument('--sha512', action="store_true", help='enable sha512 option for pam_unix.so module')
    parser.add_argument('--krb5', action="store_true", help='enable pam_krb5.so module')
    parser.add_argument('--minimal', action="store_true", help='install minimalistic PAM stack')
    parser.add_argument('--debug', action="store_true", help='enable debug for selected modules')
    parser.add_argument('--nullok', action="store_true", help='enable nullok option for pam_unix.so module')

    parsed_args = parser.parse_args()
    processed = process_args(parsed_args)

    parse_templates(processed)


def process_args(args):
    # make sure that output directory exists
    pathlib.Path("stack").mkdir(parents=True, exist_ok=True)

    blank_variables = [
        "krb5_authtok",
        "unix_authtok",
        "unix_extended_encryption",
        "likeauth",
        "nullok",
        "local_users_only"
    ]

    # create a blank dictionary
    # then add in our parsed args
    output = dict.fromkeys(blank_variables, "")
    output.update(vars(args))

    # unconditional variables
    output["likeauth"] = "likeauth"
    output["unix_authtok"] = "use_authtok"

    if args.debug:
        output["debug"] = "debug"

    if args.nullok:
        output["nullok"] = "nullok"

    if args.krb5:
        output["krb5_params"] = "{0} ignore_root try_first_pass".format("debug").strip()

    if args.sssd:
        output["local_users_only"] = "local_users_only"

    if args.yescrypt:
        output["unix_extended_encryption"] = "yescrypt shadow"
    elif args.sha512:
        output["unix_extended_encryption"] = "sha512 shadow"
    else:
        output["unix_extended_encryption"] = "md5 shadow"

    return output


def parse_templates(processed_args):
    load = FileSystemLoader('')
    env = Environment(loader=load, trim_blocks=True, lstrip_blocks=True, keep_trailing_newline=True)

    templates = [
        "login",
        "other",
        "passwd",
        "system-local-login",
        "system-remote-login",
        "su",
        "system-auth",
        "system-login",
        "system-services"
    ]

    for template_name in templates:
        template = env.get_template('templates/{0}.tpl'.format(template_name))

        with open('stack/{0}'.format(template_name), "w+") as output:
            rendered_template = template.render(processed_args)

            # Strip all intermediate lines to not worry about appeasing Jinja
            lines = rendered_template.split("\n")
            lines = [line.strip() for line in lines if line]
            rendered_template = "\n".join(lines)

            if rendered_template:
                output.write(rendered_template + "\n")


if __name__ == "__main__":
    main()
