from datetime import datetime

import pytest
from testtools.assertions import assert_that
from testtools.matchers import Equals, MatchesListwise
from testtools.twistedsupport import succeeded
from treq.testing import StubTreq
from twisted.internet.defer import succeed
from twisted.internet.task import Clock
from txacme.testing import FakeClient, MemoryStore
from txacme.util import generate_private_key

from marathon_acme.clients import MarathonClient, MarathonLbClient
from marathon_acme.service import MarathonAcme, parse_domain_label
from marathon_acme.tests.fake_marathon import (
    FakeMarathon, FakeMarathonAPI, FakeMarathonLb)


class TestParseDomainLabel(object):
    def test_single_domain(self):
        domains = parse_domain_label('example.com')
        assert_that(domains, Equals(['example.com']))

    def test_whitespace(self):
        domains = parse_domain_label(' ')
        assert_that(domains, Equals([]))

    def test_multiple_domains(self):
        domains = parse_domain_label('example.com,example2.com')
        assert_that(domains, Equals(['example.com', 'example2.com']))

    def test_multiple_domains_whitespace(self):
        domains = parse_domain_label(' example.com, example2.com ')
        assert_that(domains, Equals(['example.com', 'example2.com']))


class TestMarathonAcme(object):

    def setup_method(self):
        self.fake_marathon = FakeMarathon()
        fake_marathon_api = FakeMarathonAPI(self.fake_marathon)
        marathon_client = MarathonClient(
            'http://localhost:8080',
            StubTreq(fake_marathon_api.app.resource()))

        self.cert_store = MemoryStore()

        self.fake_marathon_lb = FakeMarathonLb()
        mlb_client = MarathonLbClient(
            ['http://localhost:9090'],
            StubTreq(self.fake_marathon_lb.app.resource()))

        key = generate_private_key(u'rsa')
        self.clock = Clock()
        self.clock.rightNow = (
            datetime.now() - datetime(1970, 1, 1)).total_seconds()
        txacme_client = FakeClient(key, self.clock)

        self.marathon_acme = MarathonAcme(
            marathon_client,
            'external',
            self.cert_store,
            mlb_client,
            lambda: succeed(txacme_client),
            self.clock
        )

    @pytest.mark.xfail(
        reason="txacme's FakeClient doesn't support HTTP challenge type")
    def test_sync_app(self):
        # Store an app in Marathon with a marathon-acme domain
        self.fake_marathon.add_app({
            'id': '/my-app_1',
            'labels': {
                'HAPROXY_GROUP': 'external',
                'MARATHON_ACME_0_DOMAIN': 'example.com'
            },
            'portDefinitions': [
                {'port': 9000, 'protocol': 'tcp', 'labels': {}}
            ]
        })

        d = self.marathon_acme.sync()
        assert_that(d, succeeded(MatchesListwise([
            succeeded(Equals('foo'))
        ])))

        # Nothing stored, nothing notified
        assert_that(self.fake_marathon_lb.check_signalled_usr1(),
                    Equals(True))

    def test_sync_no_apps(self):
        d = self.marathon_acme.sync()
        assert_that(d, succeeded(Equals([])))

        # Nothing stored, nothing notified
        assert_that(self.fake_marathon_lb.check_signalled_usr1(),
                    Equals(False))

    def test_sync_app_no_domains(self):
        # Store an app in Marathon with no domain
        self.fake_marathon.add_app({
            'id': '/my-app_1',
            'labels': {
                'HAPROXY_0_VHOST': 'example.com'
            },
            'portDefinitions': [
                {'port': 9000, 'protocol': 'tcp', 'labels': {}}
            ]
        })

        d = self.marathon_acme.sync()
        assert_that(d, succeeded(Equals([])))

        # Nothing stored, nothing notified
        assert_that(self.fake_marathon_lb.check_signalled_usr1(),
                    Equals(False))

@@ -28,21 +28,64 @@
 me%0A%0A
-import pytest
+from acme import challenges%0Afrom acme.jose import JWKRSA
 %0Afro
@@ -167,25 +167,8 @@
 uals
-, MatchesListwise
 %0Afro
@@ -1861,16 +1861,27 @@
   key = 
+JWKRSA(key=
 generate
@@ -1900,16 +1900,17 @@
 (u'rsa')
+)
 %0A       
@@ -2081,16 +2081,133 @@
 f.clock)
+%0A        # Patch on support for HTTP challenge types%0A        txacme_client._challenge_types.append(challenges.HTTP01)
 %0A%0A      
@@ -2431,106 +2431,8 @@
  )%0A%0A
-    @pytest.mark.xfail(%0A        reason=%22txacme's FakeClient doesn't support HTTP challenge type%22)%0A
     
@@ -2925,217 +2925,21 @@
 ded(
-MatchesListwise(%5B%0A            succeeded(Equals('foo'))%0A        %5D)))%0A%0A        # Nothing stored, nothing notified%0A        assert_that(self.fake_marathon_lb.check_signalled_usr1(),%0A                    Equals(True
+Equals('foo')
 ))%0A%0A

Fix some things in service tests, break some others