# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from unittest import skipUnless

from django.test import TestCase
from django.conf import settings

from coin.offers.models import Offer, OfferSubscription
from coin.resources.models import IPPool, IPSubnet
from coin.members.models import Member
from coin.members.tests import MemberTestsUtils

from .models import VPNConfiguration

USING_POSTGRES = (settings.DATABASES['default']['ENGINE']
                  ==
                  'django.db.backends.postgresql_psycopg2')

class VPNTestCase(TestCase):
    fixtures = ['example_pools.json', 'offers.json']

    def setUp(self):
        self.v6_pool = IPPool.objects.get(default_subnetsize=56)
        self.v4_pool = IPPool.objects.get(default_subnetsize=32)
        self.offer = Offer.objects.filter(configuration_type="VPNConfiguration")[0]

        # Create a member.
        cn = MemberTestsUtils.get_random_username()
        self.member = Member.objects.create(first_name=u"Toto",
                                            last_name=u"L'artichaut",
                                            username=cn)

        # Create a new VPN with subnets.
        # We need Django to call clean() so that magic happens.
        abo = OfferSubscription(offer=self.offer, member=self.member)
        abo.full_clean()
        abo.save()
        vpn = VPNConfiguration(offersubscription=abo)
        vpn.full_clean()
        vpn.save()
        v6 = IPSubnet(ip_pool=self.v6_pool, configuration=vpn)
        v6.full_clean()
        v6.save()
        v4 = IPSubnet(ip_pool=self.v4_pool, configuration=vpn)
        v4.full_clean()
        v4.save()

        # Create additional VPN, they should automatically be attributed a
        # new login.
        for i in range(5):
            abo = OfferSubscription(offer=self.offer, member=self.member)
            abo.full_clean()
            abo.save()
            vpn = VPNConfiguration(offersubscription=abo)
            vpn.full_clean()
            vpn.save()

    def tearDown(self):
        """Properly clean up objects, so that they don't stay in LDAP"""
        for vpn in VPNConfiguration.objects.all():
            vpn.delete()
        Member.objects.get().delete()

    @skipUnless(USING_POSTGRES, "Using a postgresql-only field")
    def test_has_ipv4_endpoint(self):
        vpn = VPNConfiguration.objects.all()[0]
        self.assertIsNotNone(vpn.ipv4_endpoint)

    @skipUnless(USING_POSTGRES, "Using a postgresql-only field")
    def test_has_correct_ipv4_endpoint(self):
        """If there is not endpoint, we consider it to be correct."""
        vpn = VPNConfiguration.objects.all()[0]
        if vpn.ipv4_endpoint is not None:
            subnet = vpn.ip_subnet.get(ip_pool=self.v4_pool)
            self.assertIn(vpn.ipv4_endpoint, subnet.inet)

    @skipUnless(USING_POSTGRES, "Using a postgresql-only field")
    def test_has_ipv6_endpoint(self):
        vpn = VPNConfiguration.objects.all()[0]
        self.assertIsNotNone(vpn.ipv6_endpoint)

    @skipUnless(USING_POSTGRES, "Using a postgresql-only field")
    def test_has_correct_ipv6_endpoint(self):
        """If there is not endpoint, we consider it to be correct."""
        vpn = VPNConfiguration.objects.all()[0]
        if vpn.ipv6_endpoint is not None:
            subnet = vpn.ip_subnet.get(ip_pool=self.v6_pool)
            self.assertIn(vpn.ipv6_endpoint, subnet.inet)

    @skipUnless(USING_POSTGRES, "Using a postgresql-only field")
    def test_change_v4subnet_is_vpn_endpoint_correct(self):
        vpn = VPNConfiguration.objects.all()[0]
        subnet = vpn.ip_subnet.get(ip_pool=self.v4_pool)
        subnet.inet = "192.168.42.42/31"
        subnet.full_clean()
        subnet.save()
        self.test_has_correct_ipv4_endpoint()

    @skipUnless(USING_POSTGRES, "Using a postgresql-only field")
    def test_change_v6subnet_is_vpn_endpoint_correct(self):
        vpn = VPNConfiguration.objects.all()[0]
        subnet = vpn.ip_subnet.get(ip_pool=self.v6_pool)
        subnet.inet = "2001:db8:4242:4200::/56"
        subnet.full_clean()
        subnet.save()
        self.test_has_correct_ipv6_endpoint()

    def test_automatic_login(self):
        vpn = VPNConfiguration.objects.all()[0]
        expected_login = vpn.offersubscription.member.username + "-vpn1"
        self.assertEqual(vpn.login, expected_login)

    def test_has_multiple_vpn(self):
        vpns = VPNConfiguration.objects.all()
        self.assertEqual(len(vpns), 6)