from ..common import *

class TD_COAP_OBS_02(CoAPTestCase):
    """
---
TD_COAP_OBS_02:
    cfg: CoAP_CFG_BASIC
    obj: Handle resource observation with NON messages
    ref: '[OBSERVE] 1.2, 3, 4'

    pre:
        - Client supports Observe option
        - Server supports Observe option
        - "Server offers an observable resource /obs-non which changes
           periodically (e.g. every 5s) which produces non-confirmable
           notifications"

    seq:
        -   s: "Client is requested to send to the server a non-confirmable
                GET request with observe option for resource /obs-non"

        -   c:
            - 'The request sent by client contains:'
            -   - Type = 1 (NON)
                - Code = 1 (GET)
                - Token value  = a value generated by the client
                - Observe option = empty

        -   c:
        - 'Server sends a notification containing:'
        -    -Type = 1 (NON)
            - Code = 2.05 (Content)
            - Content-format = the same for all notifications
            - Token value = same as one found in the step 2
            - Observe option indicating increasing values

        -   v: Client displays the received information

    """
    @classmethod
    @typecheck
    def get_stimulis(cls) -> list_of(Value):
        """
        Get the stimulis of this test case. This has to be be implemented into
        each test cases class.

        :return: The stimulis of this TC
        :rtype: [Value]
        """
        return [
            CoAP(type='non', code='get', opt=Opt(CoAPOptionObserve(0), CoAPOptionUriPath("obs-non")))
        ]

    def run(self):
        # Step 2
        self.match("client", CoAP (code="get",
        opt=self.uri("/obs-non", CoAPOptionObserve (0))))

        token = self.coap["tok"]

        self.next()
        if self.match("server",CoAP(type="ack"),None):
            if not self.match("server",
                              CoAP(code=2.05,
                                   opt=Opt(CoAPOptionObserve(),
                                           CoAPOptionContentFormat()
                                           )
                                   )
                              ):
                raise self.Stop()

            content_format = self.coap["opt"][CoAPOptionContentFormat]["val"]
            index          = self.coap["opt"][CoAPOptionObserve]["val"]
            self.next()
        else:
            content_format = self.coap["opt"][CoAPOptionContentFormat]["val"]
            index          = self.coap["opt"][CoAPOptionObserve]["val"]
            self.next()

            # match at least 2 other notifications
            for i in range (2):
                # Step 3
                if not self.match("server", CoAP(type="non", code=2.05, opt=Opt(
                CoAPOptionObserve(),
                CoAPOptionContentFormat(),
                ))):
                    raise self.Stop()
                self.match("server", CoAP(tok = token), "fail")
                self.match("server", CoAP(opt = Opt (CoAPOptionContentFormat(content_format))), "fail")

                new_index = self.coap["opt"][CoAPOptionObserve]["val"]

                self.next()
                self.set_verdict (("pass" if new_index > index else "fail"),
                "value of observe option must be increasing")
                raise self.Stop()
