# coding=utf-8

"""
Testing CoAP requests
"""
import json
import os
import tempfile
import unittest

import pycolo as coap
from pycolo.request import request
from pycolo.endpoint import Endpoint
from pycolo.exceptions import InvalidURL, COAPError
from tests.examples.TestCoAPbin import coapbin


class CarelessTest(unittest.TestCase):
    """
    Careless testing suite
    """

    def setUp(self):
        """
        Set up of a careless server for request testing
        """
        self.server = Endpoint(__name__)

        def careless(self, request):
            """
            This implements a 'separate' resource for demonstration purposes.
            Defines a resource that returns a response in a separate CoAP
            Message

            1 °) promise the client that this request will be acted upon
            by sending an Acknowledgement...

            :param request:
            """
            request.accept()  # ... and then do nothing. Pretty mean.

        self.server.route("careless",
                      title="This resource will ACK anything, "
                            "but never send a separate response",
                      resourceType="SeparateResponseTester",
                      function=careless)

    def test_careless(self):
        """
        todo
        """
        pass


class RequestTestSuite(unittest.TestCase):
    """
    Request testing suite
    """

    def setUp(self):
        """
        Set up of the test set
        """
        self.coapbin = coapbin(__name__)

    def test_invalid_url(self):
        """
        Test for invalid URL
        """
        self.assertRaises(ValueError, coap.get("foobar"))

    def test_path_is_not_double_encoded(self):
        """
        Double encoding testing
        """
        r = coap.get(self.coapbin("/get/test case"))
        self.assertEqual(r.path_url, "/get/test%20case")

    def test_params_are_added_before_fragment(self):
        """
        Testing the correct order or url encoding
        """
        r = request(
            "coap://example.com/path#fragment", params={"a": "b"})
        self.assertEqual(r.full_url,
            "coap://example.com/path?a=b#fragment")
        r = request(
            "coap://example.com/path?key=value#fragment", params={"a": "b"})
        self.assertEqual(r.full_url,
            "coap://example.com/path?key=value&a=b#fragment")

    def test_params_accepts_kv_list(self):
        """
        Testing parameters encoding
        """
        r = request('coap://example.com/path',
                params=[('a', 'b')])
        self.assertEqual(r.full_url, 'coap://example.com/path?a=b')

    def test_200_OK_GET(self):
        """
        Testing OK status
        """
        self.assertEqual(coap.get(self.coapbin('get')).status_code,
                         200)

    def test_response_sent(self):
        """
        Testing "sent" status
        """
        r = coap.get(self.coapbin('get'))
        self.assertTrue(r.sent)

    def test_302_ALLOW_REDIRECT_GET(self):
        """
        Testing redirection
        """
        self.assertEqual(coap.get(self.coapbin('redirect', '1')).status_code,
                         200)

    def test_COAP_302_GET(self):
        """
        Testing redirection
        """
        r = coap.get(self.coapbin('redirect', '1'), allow_redirects=False)
        self.assertEqual(r.status_code, 302)

    def test_COAP_200_OK_GET_WITH_MIXED_PARAMS(self):
        """
        Test encoding coming from different sources
        """
        r = coap.get(self.coapbin('get') + '?test=true',
                     params={'q': 'test'},
                     headers={'User-agent': 'pycolo'})
        self.assertEqual(r.status_code, 200)

    def test_COAP_200_OK_PUT(self):
        """
        Test PUT request
        """
        r = coap.put(self.coapbin('put'))
        self.assertEqual(r.status_code, 200)

    def test_POST_FILES(self):
        """
        Test POST of text, files...
        """
        url = self.coapbin('post')

        post1 = coap.post(url, data={'some': 'data'})
        self.assertEqual(post1.status_code, 200)

        with open(__file__) as f:
            post2 = coap.post(url, files={'some': f})
            post3 = coap.post(url, files=[('some', f)])
        self.assertEqual(post2.status_code, 200)
        self.assertEqual(post3.status_code, 200)

        post4 = coap.post(url, data=json.dumps({"some": "json"}))
        self.assertEqual(post4.status_code, 200)

        try:
            coap.post(url, files=['bad file data'])
        except ValueError:
            pass

    def test_POST_FILES_WITH_PARAMS(self):
        """
        Test POST of files with parameters
        """
        with open(__file__) as f:
            url = self.coapbin('post')
            post1 = coap.post(url,
                              data={'some': 'data'},
                              files={'some': f})
            post2 = coap.post(url,
                              data={'some': 'data'},
                              files=[('some', f)])
            post3 = coap.post(url,
                              data=[('some', 'data')],
                              files=[('some', f)])

        self.assertEqual(post1.status_code, 200)
        self.assertEqual(post2.status_code, 200)
        self.assertEqual(post3.status_code, 200)

    def test_POST_FILES_WITH_CJK_PARAMS(self):
        """
        Test good unicode support for parameters in a POST request.
        """
        with open(__file__) as f:
            url = self.coapbin('post')
     
       post1 = coap.post(url, data={'some': '中文'}, files={'some': f})
            post2 = coap.post(url, data={'some': '日本語'}, files=[('some', f)])
            post3 = coap.post(url, data=[('some', '한국의')], files=[('some', f)])

        self.as
sertEqual(post1.status_code, 200)
        self.assertEqual(post2.status_code, 200)
        self.assertEqual(post3.status_code, 200)

    def test_POST_FILES_WITH_HEADERS(self):
        """
        Test POST with headers
        """
        url = self.coapbin('post')

        with open(__file__) as f:

            post2 = coap.post(url,
                files={'some': f})

        self.assertEqual(post2.status_code, 200)

    def test_nonzero_evaluation(self):
        """
        Test boolean support
        """
        r = coap.get(self.coapbin('status', '500'))
        self.assertEqual(bool(r), False)

        r = coap.get(self.coapbin('/get'))
        self.assertEqual(bool(r), True)

    def test_request_ok_set(self):
        """
        Test ok support
        """
        r = coap.get(self.coapbin('status', '404'))
        self.assertEqual(r.ok, False)

    def test_status_raising(self):
        """
        Test for basic exception support
        """
        r = coap.get(self.coapbin('status', '404'))
        self.assertRaises(COAPError, r.raise_for_status)

        r = coap.get(self.coapbin('status', '200'))
        self.assertFalse(r.error)
        r.raise_for_status()

    def test_default_status_raising(self):
        """
        Test for default exception
        """
        config = {'danger_mode': True}
        args = [self.coapbin('status', '404')]
        kwargs = {"config": config}
        self.assertRaises(COAPError, coap.get, *args, **kwargs)

        r = coap.get(self.coapbin('status', '200'))
        self.assertEqual(r.status_code, 200)

    def test_response_has_unicode_url(self):
        """
        Testing unicode URL
        """
        url = self.coapbin('get')
        response = coap.get(url)
        coap.get(url, params={'foo': 'føø'})
        coap.get(url, params={'føø': 'føø'})
        coap.get(url, params={'føø': 'føø'})
        coap.get(url, params={'foo': 'foo'})
        coap.get(self.coapbin('ø'), params={'foo': 'foo'})
        self.assertTrue(isinstance(response.url, str))

    def test_url_encoded_post_data(self):
        """
        Test post data
        """
        content = "foobar"
        r = coap.post(self.coapbin('post'), data={"test": content})

        self.assertEqual(r.status_code, 200)
        self.assertEqual(r.headers['content-type'], 'application/json')
        self.asse