from subprocess import PIPE, Popen

from core.models import Service, TenantWithContainer
from django.db import transaction
from xos.exceptions import XOSConfigurationError, XOSValidationError

VPN_KIND = "vpn"


class VPNService(Service):
    """Defines the Service for creating VPN servers."""
    KIND = VPN_KIND
    OPENVPN_PREFIX = "/opt/openvpn/"
    """The location of the openvpn EASY RSA files and PKIs."""
    SERVER_PREFIX = OPENVPN_PREFIX + "server-"
    """The prefix for server PKIs."""
    VARS = OPENVPN_PREFIX + "vars"
    """The location of the vars file with information for using EASY RSA."""
    EASYRSA_LOC = OPENVPN_PREFIX + "easyrsa3/easyrsa"
    """The location of the EASY RSA binary."""
    EASYRSA_COMMAND_PREFIX = EASYRSA_LOC + " --vars=" + VARS
    """Prefix for EASY RSA commands."""

    @classmethod
    def execute_easyrsa_command(cls, pki_dir, command):
        """Executes the given EASY RSA command using the given PKI.

        Parameters:
            pki_dir (str): The directory for the pki to execute the command on.
            command (str): The command to execute using ESAY RSA.
        """
        full_command = (
            VPNService.EASYRSA_COMMAND_PREIX + " --pki-dir=" +
            pki_dir + " " + command)
        proc = Popen(
            full_command, shell=True, stdout=PIPE, stderr=PIPE
        )
        (stdout, stderr) = proc.communicate()
        if (proc.returncode != 0):
            raise XOSConfigurationError(
                full_command + " failed with standard out:" + str(stdout) +
                " and stderr: " + str(stderr))

    @classmethod
    def get_pki_dir(cls, tenant):
        """Gets the directory of the PKI for the given tenant.

        Parameters:
            tenant (services.vpn.models.VPNTenant): The tenant to get the PKI directory for.

        Returns:
            str: The pki directory for the tenant.
        """
        return VPNService.SERVER_PREFIX + str(tenant.id)

    class Meta:
        proxy = True
        # The name used to find this service, all directories are named this
        app_label = "vpn"
        verbose_name = "VPN Service"

    default_attributes = {'exposed_ports': None,
                          'exposed_ports_str': None}

    @property
    def exposed_ports(self):
        """Mapping[str, list(str)]: maps protocols to a list of ports for that protocol."""
        return self.get_attribute("exposed_ports",
                                  self.default_attributes["exposed_ports"])

    @exposed_ports.setter
    def exposed_ports(self, value):
        self.set_attribute("exposed_ports", value)

    @property
    def exposed_ports_str(self):
        """str: a raw str representing the exposed ports."""
        return self.get_attribute("exposed_ports_str",
                                  self.default_attributes["exposed_ports_str"])

    @exposed_ports_str.setter
    def exposed_ports_str(self, value):
        self.set_attribute("exposed_ports_str", value)

    def get_next_available_port(self, protocol):
        """Gets the next free port for the given protocol.

        Parameters:
            protocol (str): The protocol to get a port for, must be tcp or udp.

        Returns:
            int: a port number.

        Raises:
            xos.exceptions.XOSValidationError: If there the protocol is not udp or tcp.
            xos.exceptions.XOSValidationError: If there are no available ports for the protocol.
        """
        if protocol != "udp" and protocol != "tcp":
            raise XOSValidationError("Port protocol must be udp or tcp")
        if not self.exposed_ports[protocol]:
            raise XOSValidationError(
                "No availble ports for protocol: " + protocol)
        tenants = [
            tenant for tenant in VPNTenant.get_tenant_objects().all()
            if tenant.protocol == protocol]
        port_numbers = self.exposed_ports[protocol]
        for port_number in port_numbers:
            if (
                len([
                    tenant for tenant in tenants
                    if tenant.port_number == port_number]) == 0):
                return port_number


class VPNTenant(TenantWithContainer):
    """Defines the Tenant for creating VPN servers."""

    class Meta:
        proxy = True
        verbose_name = "VPN Tenant"

    KIND = VPN_KIND

    sync_attributes = ("nat_ip", "nat_mac",)

    default_attributes = {'vpn_subnet': None,
                          'server_network': None,
                          'clients_can_see_each_other': True,
                          'is_persistent': True,
                          'port': None,
                          'use_ca_from_id': None,
                          'failover_server_ids': list(),
                          'protocol': None}

    def __init__(self, *args, **kwargs):
        vpn_services = VPNService.get_service_objects().all()
        if vpn_services:
            self._meta.get_field(
                "provider_service").default = vpn_services[0].id
        super(VPNTenant, self).__init__(*args, **kwargs)

    def save(self, *args, **kwargs):
        super(VPNTenant, self).save(*args, **kwargs)
        model_policy_vpn_tenant(self.pk)

    def delete(self, *args, **kwargs):
        self.cleanup_container()
        super(VPNTenant, self).delete(*args, **kwargs)

    @property
    def protocol(self):
        """str: The protocol that this tenant is listening on."""
        return self.get_attribute(
            "protocol", self.default_attributes["protocol"])

    @protocol.setter
    def protocol(self, value):
        self.set_attribute("protocol", value)

    @property
    def use_ca_from_id(self):
        """int: The ID of VPNTenant to use to obtain a CA."""
        return self.get_attribute(
            "use_ca_from_id", self.default_attributes["use_ca_from_id"])

    @use_ca_from_id.setter
    def use_ca_from_id(self, value):
        self.set_attribute("use_ca_from_id", value)

    @property
    def addresses(self):
        """Mapping[str, str]: The ip, mac address, and subnet of the NAT
            network of this Tenant."""
        if (not self.id) or (not self.instance):
            return {}

        addresses = {}
        for ns in self.instance.ports.all():
            if "nat" in ns.network.name.lower():
                addresses["ip"] = ns.ip
                addresses["mac"] = ns.mac
                break

        return addresses

    # This getter is necessary because nat_ip is a sync_attribute
    @property
    def nat_ip(self):
        """str: The IP of this Tenant on the NAT network."""
        return self.addresses.get("ip", None)

    # This getter is necessary because nat_mac is a sync_attribute
    @property
    def nat_mac(self):
        """str: The MAC address of this Tenant on the NAT network."""
        return self.addresses.get("mac", None)

    @property
    def server_network(self):
        """str: The IP address of the server on the VPN."""
        return self.get_attribute(
            'server_network',
            self.default_attributes['server_network'])

    @server_network.setter
    def server_network(self, value):
        self.set_attribute("server_network", value)

    @property
    def vpn_subnet(self):
        """str: The IP address of the client on the VPN."""
        return self.get_attribute(
            'vpn_subnet',
            self.default_attributes['vpn_subnet'])

    @vpn_subnet.setter
    def vpn_subnet(self, value):
        self.set_attribute("vpn_subnet", value)

    @property
    def is_persistent(self):
        """bool: True if the VPN connection is persistence, false otherwise."""
        return self.get_attribute(
            "is_persistent",
            self.default_attributes['is_persistent'])

    @is_persistent.setter
    def is_persistent(self, value):
        self.set_attribute("is_persistent", value)

    @property
    def failover_server_ids(self):
        """list(int): The IDs of the VPNTenants to use as failover servers."""
        return self.get_attribute(
            "failover_server_ids", self.default_attributes["failover_server_ids"])

    @failover_server_ids.setter
    def failover_server_ids(self, value):
        self.set_attribute("failover_server_ids", value)

    @property
    def clients_can_see_each_other(self):
        """bool: True if the client can see the subnet of the server, false
            otherwise."""
        return self.get_attribute(
            "clients_can_see_each_other",
            self.default_attributes['clients_can_see_each_other'])

    @clients_can_see_each_other.setter
    def clients_can_see_each_other(self, value):
        self.set_attribute("clients_can_see_each_other", value)

    @property
    def port_number(self):
        """int: the integer representing the port number for this server"""
        return self.get_attribute("port", self.default_attributes['port'])

    @port_number.setter
    def port_number(self, value):
        self.set_attribute("port", value)

    def create_client_script(self, client_name):
        """Create a script that a client can use to access this VPNTenant.

        Parameters:
            client_name (str): The name of the client to use when creating the cerificate.

        Returns:
            str: A str representing the client script.
        """
        pki_dir = VPNService.get_pki_dir(self)
        script = ""
        # write the configuration portion
        script += ("printf \"%b\" \"")
        script += self.generate_client_conf(client_name)
        script += ("\" > client.conf\n")
        script += ("printf \"%b\" \"")
        for line in self.get_ca_crt(pki_dir):
            script += (line.rstrip() + r"\n")
        script += ("\" > ca.crt\n")
        script += ("printf \"%b\" \"")
        for line in self.get_client_cert(client_name, pki_dir):
            script += (line.rstrip() + r"\n")
        script += ("\" > " + client_name + ".crt\n")
        script += ("printf \"%b\" \"")
        for line in self.get_client_key(client_name, pki_dir):
            script += (line.rstrip() + r"\n")
        script += ("\" > " + client_name + ".key\n")
        # make sure openvpn is installed
        script += ("apt-get update\n")
        script += ("apt-get install openvpn -y\n")
        script += ("openvpn client.conf\n")
        # close the script
        return script

    def get_ca_crt(self, pki_dir):
        """Gets the lines fo the ca.crt file for this VPNTenant.

        Parameters:
            pki_dir (str): The PKI directory to look in.

        Returns:
            list(str): The lines of the ca.crt file for this VPNTenant.
        """
        with open(pki_dir + "/ca.crt", 'r') as f:
            return f.readlines()

    def get_client_cert(self, client_name, pki_dir):
        """Gets the lines fo the crt file for a client.

        Parameters:
            pki_dir (str): The PKI directory to look in.
            client_name (str): The client name to use.

        Returns:
            list(str): The lines of the crt file for the client.
        """
        with open(pki_dir + "/issued/" + client_name + ".crt", 'r') as f:
            return f.readlines()

    def get_client_key(self, client_name, pki_dir):
        """Gets the lines fo the key file for a client.

        Parameters:
            pki_dir (str): The PKI directory to look in.
            client_name (str): The client name to use.

        Returns:
            list(str): The lines of the key file for the client.
        """
        with open(pki_dir + "/private/" + client_name + ".key", 'r') as f:
            return f.readlines()

    def generate_client_conf(self, client_name):
        """Returns the conf file for the given client.

        Parameters:
            client_name (str): The client name to use.

        Returns:
            str: Generates the client configuration to use to connect to this VPN server.
        """
        conf = ("client\n" +
                "dev tun\n" +
                "remote-cert-tls server\n" +
                "resolv-retry 60\n" +
                "nobind\n" +
                "ca ca.crt\n" +
                "cert " + client_name + ".crt\n" +
                "key " + client_name + ".key\n" +
                "verb 3\n" +
                self.get_remote_line(
                    self.nat_ip, self.port_number, self.protocol))
        for remote in self.failover_server_ids:
            tenant = VPNTenant.get_tenant_objects().filter(pk=remote)[0]
            conf += self.get_remote_line(
                tenant.nat_ip, tenant.port_number, tenant.protocol)

        if self.is_persistent:
            conf += "persist-tun\n"
            conf += "persist-key\n"

        return conf

    def get_remote_line(self, host, port_number, protocol):
        return ("remote " + str(host) + " " + str(port_number) + " " +
                str(protocol) + "\n")


def model_policy_vpn_tenant(pk):
    """Manages the container for the VPN Tenant.

    Parameters
        pk (int): The ID of this VPNTenant.
    """
    # This section of code is atomic to prevent race conditions
    with transaction.atomic():
        # We find all of the tenants that are waiting to update
        tenant = VPNTenant.objects.select_for_update().filter(pk=pk)
        if not tenant:
            return
        # Since this code is atomic it is safe to always use the first tenant
        tenant = tenant[0]
        tenant.manage_container()
