from hashlib import sha3_256
from base64 import b64decode, b64encode
from binascii import hexlify
from uuid import UUID

defaults = {
    'apt': {
        'packages': {
            'gocryptfs': {},
            'fuse': {},
            'socat': {},
        },
    },
    'gocryptfs': {
        'paths': {},
    },
}


@metadata_reactor.provides(
    'gocryptfs',
)
def config(metadata):
    return {
        'gocryptfs': {
            'masterkey': hexlify(b64decode(
                str(repo.vault.random_bytes_as_base64_for(metadata.get('id'), length=32))
            )).decode(),
            'salt': b64encode(
                sha3_256(UUID(metadata.get('id')).bytes).digest()
            ).decode(),
        },
    }


@metadata_reactor.provides(
    'gocryptfs',
)
def paths(metadata):
    paths = {}
    
    for path, options in metadata.get('gocryptfs/paths').items():
        paths[path] = {
            'id': hexlify(sha3_256(path.encode()).digest()[:8]).decode(),
        }
    
    return {
        'gocryptfs': {
            'paths': paths,
        },
    }



@metadata_reactor.provides(
    'systemd/services',
)
def systemd(metadata):
    services = {}
    
    for path, options in metadata.get('gocryptfs/paths').items():
        services[f'gocryptfs-{options["id"]}'] = {
            'content': {
                'Unit': {
                    'Description': f'gocryptfs@{path} ({options["id"]})',
                    'After': {
                      'filesystem.target',
                      'zfs.target',
                    },
                },
                'Service': {
                    'RuntimeDirectory': 'gocryptfs',
                    'Environment': {
                        'MASTERKEY': metadata.get('gocryptfs/masterkey'),
                        'SOCKET': f'/var/run/gocryptfs/{options["id"]}',
                        'PLAIN': path,
                        'CIPHER': options["mountpoint"]
                    },
                    'ExecStart': [
                        '/usr/bin/gocryptfs -fg -plaintextnames -reverse -masterkey $MASTERKEY -ctlsock $SOCKET $PLAIN $CIPHER',
                    ],
                    'ExecStopPost': [
                        '/usr/bin/umount $CIPHER'
                    ],
                },
            },
            'needs': [
                'pkg_apt:gocryptfs',
                'pkg_apt:fuse',
                'pkg_apt:socat',
                'file:/etc/gocryptfs/masterkey',
                'file:/etc/gocryptfs/gocryptfs.conf',
            ],
            'triggers': [
                f'svc_systemd:gocryptfs-{options["id"]}:restart',
            ],
        }

    return {
        'systemd': {
            'services': services,
        },
    }