# -*- coding: utf-8 -*-

import os
import subprocess

from . import paths

def get_authorized_keys():
    # Fetches content of root's authorized_files
    try:
        with open(paths.AUTHORIZED_KEYS) as f:
            return f.read()
    except FileNotFoundError:
        return ''

def set_authorized_keys(keys):
    # Saves content of root's authorized_files
    with open(paths.AUTHORIZED_KEYS, 'w') as f:
        f.write(keys)
    # Enable or disable SSH service
    if keys.strip():
        subprocess.run(['/sbin/rc-update', 'add', 'sshd', 'boot'])
        subprocess.run(['/sbin/service', 'sshd', 'start'])
    else:
        subprocess.run(['/sbin/service', 'sshd', 'stop'])
        subprocess.run(['/sbin/rc-update', 'del', 'sshd', 'boot'])

def is_wireguard_running():
    # Returns status of wg0 interface (inferred from existence of its config file)
    return os.path.exists(paths.WG_CONF_FILE)

def regenerate_wireguard_key():
    # Regenerates WireGuard key pair for wg0 interface
    was_running = is_wireguard_running()
    if was_running:
        stop_wireguard()
    privkey = subprocess.run(['/usr/bin/wg', 'genkey'], stdout=subprocess.PIPE).stdout.decode().strip()
    with open(paths.WG_CONF_DISABLED) as f:
        conf_lines = f.readlines()
    conf_lines[2] = f'PrivateKey = {privkey}\n'
    with open(paths.WG_CONF_DISABLED, 'w') as f:
        f.writelines(conf_lines)
    if was_running:
        start_wireguard()
    return privkey

def get_wireguard_conf():
    # Returns dictionary with WireGuard wg0 interface VPN IP, public key, listen port and peer info
    result = {'running': is_wireguard_running()}
    # IP
    with open(paths.INTERFACES_FILE) as f:
        for line in f.read().splitlines():
            if '172.17.255' in line:
                result['ip'] = line.split('.')[-1]
                break
    # Listen port and peers
    with open(paths.WG_CONF_FILE if result['running'] else paths.WG_CONF_DISABLED) as f:
        conf_lines = f.read().splitlines()
    result['port'] = conf_lines[1].split()[2]
    result['peers'] = '\n'.join(conf_lines[4:])
    # Public key
    privkey = conf_lines[2].split()[2]
    if privkey == 'None':
        privkey = regenerate_wireguard_key()
    result['pubkey'] = subprocess.run(['/usr/bin/wg', 'pubkey'], input=privkey.encode(), stdout=subprocess.PIPE).stdout.decode().strip()
    return result

def set_wireguard_conf(ip, port, peers):
    # Sets WireGuard wg0 interface VPN IP, listen port and peer info
    was_running = is_wireguard_running()
    if was_running:
        stop_wireguard()
    # IP
    interface_lines = []
    with open(paths.INTERFACES_FILE) as f:
        for line in f.readlines():
            if '172.17.255' in line:
                line = f'    address 172.17.255.{ip}\n'
            interface_lines.append(line)
    with open(paths.INTERFACES_FILE, 'w') as f:
        f.writelines(interface_lines)
    # Recreate config (listen port and peers)
    with open(paths.WG_CONF_DISABLED) as f:
        conf_lines = f.readlines()[:4]
    conf_lines[1] = f'ListenPort = {port}\n'
    with open(paths.WG_CONF_DISABLED, 'w') as f:
        f.writelines(conf_lines)
        f.write(peers)
    if was_running:
        start_wireguard()

def start_wireguard():
    # Sets up WireGuard interface
    try:
        os.rename(paths.WG_CONF_DISABLED, paths.WG_CONF_FILE)
    except FileNotFoundError:
        subprocess.run(['/sbin/ifdown', 'wg0'])
    subprocess.run(['/sbin/ifup', 'wg0'])

def stop_wireguard():
    # Tears down WireGuard interface
    subprocess.run(['/sbin/ifdown', 'wg0'])
    try:
        os.rename(paths.WG_CONF_FILE, paths.WG_CONF_DISABLED)
    except FileNotFoundError:
        pass
