from . import osmapi_test
from datetime import datetime
import osmapi
from urllib import parse as urlparse


class TestOsmApiNotes(osmapi_test.TestOsmApi):
    def test_NotesGet(self):
        self._session_mock()

        result = self.api.NotesGet(-1.4998534, 45.9667901, -1.4831815, 52.4710193)

        args, kwargs = self.session_mock.request.call_args
        self.assertEqual(args[0], "GET")
        urlParts = urlparse.urlparse(args[1])
        params = urlparse.parse_qs(urlParts.query)
        self.assertEqual(params["bbox"][0], "-1.499853,45.966790,-1.483181,52.471019")
        self.assertEqual(params["limit"][0], "100")
        self.assertEqual(params["closed"][0], "7")

        self.assertEqual(len(result), 14)
        self.assertEqual(
            result[2],
            {
                "id": "231775",
                "lon": -1.4929605,
                "lat": 52.4107312,
                "date_created": datetime(2014, 8, 28, 19, 25, 37),
                "date_closed": datetime(2014, 9, 27, 9, 21, 41),
                "status": "closed",
                "comments": [
                    {
                        "date": datetime(2014, 8, 28, 19, 25, 37),
                        "action": "opened",
                        "text": "Is it Paynes or Payne's",
                        "html": "<p>Is it Paynes or Payne's</p>",
                        "uid": "1486336",
                        "user": "Wyken Seagrave",
                    },
                    {
                        "date": datetime(2014, 9, 26, 13, 5, 33),
                        "action": "commented",
                        "text": "Royal Mail's postcode finder has PAYNES LANE",
                        "html": (
                            "<p>Royal Mail's postcode finder " "has PAYNES LANE</p>"
                        ),
                        "uid": None,
                        "user": None,
                    },
                ],
            },
        )

    def test_NotesGet_empty(self):
        self._session_mock()

        result = self.api.NotesGet(
            -93.8472901, 35.9763601, -80, 36.176360100000004, limit=1, closed=0
        )

        args, kwargs = self.session_mock.request.call_args
        self.assertEqual(args[0], "GET")
        urlParts = urlparse.urlparse(args[1])
        params = urlparse.parse_qs(urlParts.query)

        self.assertEqual(params["limit"][0], "1")
        self.assertEqual(params["closed"][0], "0")

        self.assertEqual(len(result), 0)
        self.assertEqual(result, [])

    def test_NoteGet(self):
        self._session_mock()

        result = self.api.NoteGet(1111)

        args, kwargs = self.session_mock.request.call_args
        self.assertEqual(args[0], "GET")
        self.assertEqual(args[1], self.api_base + "/api/0.6/notes/1111")

        self.assertEqual(
            result,
            {
                "id": "1111",
                "lon": 12.3133135,
                "lat": 37.9305489,
                "date_created": datetime(2013, 5, 1, 20, 58, 21),
                "date_closed": datetime(2013, 8, 21, 16, 43, 26),
                "status": "closed",
                "comments": [
                    {
                        "date": datetime(2013, 5, 1, 20, 58, 21),
                        "action": "opened",
                        "text": "It does not exist this path",
                        "html": "<p>It does not exist this path</p>",
                        "uid": "1363438",
                        "user": "giuseppemari",
                    },
                    {
                        "date": datetime(2013, 8, 21, 16, 43, 26),
                        "action": "closed",
                        "text": "there is no path signed",
                        "html": "<p>there is no path signed</p>",
                        "uid": "1714220",
                        "user": "luschi",
                    },
                ],
            },
        )

    def test_NoteGet_invalid_xml(self):
        self._session_mock()

        with self.assertRaises(osmapi.XmlResponseInvalidError):
            self.api.NoteGet(1111)

    def test_NoteCreate(self):
        self._session_mock(auth=True)

        note = {"lat": 47.123, "lon": 8.432, "text": "This is a test"}
        result = self.api.NoteCreate(note)

        args, kwargs = self.session_mock.request.call_args
        self.assertEqual(args[0], "POST")
        urlParts = urlparse.urlparse(args[1])
        params = urlparse.parse_qs(urlParts.query)
        self.assertEqual(params["lat"][0], "47.123")
        self.assertEqual(params["lon"][0], "8.432")
        self.assertEqual(params["text"][0], "This is a test")

        self.assertEqual(
            result,
            {
                "id": "816",
                "lat": 47.123,
                "lon": 8.432,
                "date_created": datetime(2014, 10, 3, 15, 21, 21),
                "date_closed": None,
                "status": "open",
                "comments": [
                    {
                        "date": datetime(2014, 10, 3, 15, 21, 22),
                        "action": "opened",
                        "text": "This is a test",
                        "html": "<p>This is a test</p>",
                        "uid": "1841",
                        "user": "metaodi",
                    }
                ],
            },
        )

    def test_NoteCreateAnonymous(self):
        self._session_mock()

        note = {"lat": 47.123, "lon": 8.432, "text": "test 123"}
        result = self.api.NoteCreate(note)

        args, kwargs = self.session_mock.request.call_args
        self.assertEqual(args[0], "POST")
        urlParts = urlparse.urlparse(args[1])
        params = urlparse.parse_qs(urlParts.query)
        self.assertEqual(params["lat"][0], "47.123")
        self.assertEqual(params["lon"][0], "8.432")
        self.assertEqual(params["text"][0], "test 123")

        self.assertEqual(
            result,
            {
                "id": "842",
                "lat": 58.3368222,
                "lon": 25.8826183,
                "date_created": datetime(2015, 1, 3, 10, 49, 39),
                "date_closed": None,
                "status": "open",
                "comments": [
                    {
                        "date": datetime(2015, 1, 3, 10, 49, 39),
                        "action": "opened",
                        "text": "test 123",
                        "html": "<p>test 123</p>",
                        "uid": None,
                        "user": None,
                    }
                ],
            },
        )

    def test_NoteComment(self):
        self._session_mock(auth=True)

        result = self.api.NoteComment(812, "This is a comment")

        args, kwargs = self.session_mock.request.call_args
        self.assertEqual(args[0], "POST")
        self.assertEqual(
            args[1], self.api_base + "/api/0.6/notes/812/comment?text=This+is+a+comment"
        )

        self.assertEqual(
            result,
            {
                "id": "812",
                "lat": 47.123,
                "lon": 8.432,
                "date_created": datetime(2014, 10, 3, 15, 11, 5),
                "date_closed": None,
                "status": "open",
                "comments": [
                    {
                        "date": datetime(2014, 10, 3, 15, 11, 5),
                        "action": "opened",
                        "text": "This is a test",
                        "html": "<p>This is a test</p>",
                        "uid": "1841",
                        "user": "metaodi",
                    },
                    {
                        "date": datetime(2014, 10, 4, 22, 36, 35),
                        "action": "commented",
                        "text": "This is a comment",
                        "html": "<p>This is a comment</p>",
                        "uid": "1841",
                        "user": "metaodi",
                    },
                ],
            },
        )

    def test_NoteCommentAnonymous(self):
        self._session_mock()

        result = self.api.NoteComment(842, "blubb")

        args, kwargs = self.session_mock.request.call_args
        self.assertEqual(args[0], "POST")
        self.assertEqual(
            args[1], self.api_base + "/api/0.6/notes/842/comment?text=blubb"
        )

        self.assertEqual(
            result,
            {
                "id": "842",
                "lat": 58.3368222,
                "lon": 25.8826183,
                "date_created": datetime(2015, 1, 3, 10, 49, 39),
                "date_closed": None,
                "status": "open",
                "comments": [
                    {
                        "date": datetime(2015, 1, 3, 10, 49, 39),
                        "action": "opened",
                        "text": "test 123",
                        "html": "<p>test 123</p>",
                        "uid": None,
                        "user": None,
                    },
                    {
                        "date": datetime(2015, 1, 3, 11, 6, 0),
                        "action": "commented",
                        "text": "blubb",
                        "html": "<p>blubb</p>",
                        "uid": None,
                        "user": None,
                    },
                ],
            },
        )

    def test_NoteCommentOnClosedNote(self):
        self._session_mock(status=409)

        with self.assertRaises(osmapi.NoteAlreadyClosedApiError) as cm:
            self.api.NoteComment(817, "Comment on closed note")

        self.assertEqual(cm.exception.status, 409)
        self.assertEqual(
            cm.exception.payload, "The note 817 was closed at 2022-04-29 20:57:20 UTC"
        )

    def test_NoteComment_non_existing_note(self):
        self._session_mock(status=404)

        with self.assertRaises(osmapi.ElementNotFoundApiError) as cm:
            self.api.NoteComment(817, "Comment on closed note")

        self.assertEqual(cm.exception.status, 404)

    def test_NoteClose(self):
        self._session_mock(auth=True)

        result = self.api.NoteClose(819, "Close this note!")

        args, kwargs = self.session_mock.request.call_args
        self.assertEqual(args[0], "POST")
        self.assertEqual(
            args[1], self.api_base + "/api/0.6/notes/819/close?text=Close+this+note%21"
        )

        self.assertEqual(
            result,
            {
                "id": "815",
                "lat": 47.123,
                "lon": 8.432,
                "date_created": datetime(2014, 10, 3, 15, 20, 57),
                "date_closed": datetime(2014, 10, 5, 16, 35, 13),
                "status": "closed",
                "comments": [
                    {
                        "date": datetime(2014, 10, 3, 15, 20, 57),
                        "action": "opened",
                        "text": "This is a test",
                        "html": "<p>This is a test</p>",
                        "uid": "1841",
                        "user": "metaodi",
                    },
                    {
                        "date": datetime(2014, 10, 5, 16, 35, 13),
                        "action": "closed",
                        "text": "Close this note!",
                        "html": "<p>Close this note!</p>",
                        "uid": "1841",
                        "user": "metaodi",
                    },
                ],
            },
        )

    def test_NoteAlreadyClosed(self):
        self._session_mock(auth=True, status=409)

        with self.assertRaises(osmapi.NoteAlreadyClosedApiError) as cm:
            self.api.NoteClose(819, "Close this note!")

        self.assertEqual(cm.exception.status, 409)
        self.assertEqual(
            cm.exception.payload, "The note 819 was closed at 2022-04-29 20:57:20 UTC"
        )

    def test_NoteReopen(self):
        self._session_mock(auth=True)

        result = self.api.NoteReopen(815, "Reopen this note!")

        args, kwargs = self.session_mock.request.call_args
        self.assertEqual(args[0], "POST")
        self.assertEqual(
            args[1],
            (self.api_base + "/api/0.6/notes/815/reopen?text=Reopen+this+note%21"),
        )

        self.assertEqual(
            result,
            {
                "id": "815",
                "lat": 47.123,
                "lon": 8.432,
                "date_created": datetime(2014, 10, 3, 15, 20, 57),
                "date_closed": None,
                "status": "open",
                "comments": [
                    {
                        "date": datetime(2014, 10, 3, 15, 20, 57),
                        "action": "opened",
                        "text": "This is a test",
                        "html": "<p>This is a test</p>",
                        "uid": "1841",
                        "user": "metaodi",
                    },
                    {
                        "date": datetime(2014, 10, 5, 16, 35, 13),
                        "action": "closed",
                        "text": "Close this note!",
                        "html": "<p>Close this note!</p>",
                        "uid": "1841",
                        "user": "metaodi",
                    },
                    {
                        "date": datetime(2014, 10, 5, 16, 44, 56),
                        "action": "reopened",
                        "text": "Reopen this note!",
                        "html": "<p>Reopen this note!</p>",
                        "uid": "1841",
                        "user": "metaodi",
                    },
                ],
            },
        )

    def test_NotesSearch(self):
        self._session_mock()

        result = self.api.NotesSearch("street")

        args, kwargs = self.session_mock.request.call_args
        self.assertEqual(args[0], "GET")
        urlParts = urlparse.urlparse(args[1])
        params = urlparse.parse_qs(urlParts.query)
        self.assertEqual(params["q"][0], "street")
        self.assertEqual(params["limit"][0], "100")
        self.assertEqual(params["closed"][0], "7")

        self.assertEqual(len(result), 3)
        self.assertEqual(
            result[1],
            {
                "id": "788",
                "lon": 11.96395,
                "lat": 57.70301,
                "date_created": datetime(2014, 7, 16, 16, 12, 41),
                "date_closed": None,
                "status": "open",
                "comments": [
                    {
                        "date": datetime(2014, 7, 16, 16, 12, 41),
                        "action": "opened",
                        "text": "One way street:\ncomment",
                        "html": "<p>One way street:\n<br />comment</p>",
                        "uid": None,
                        "user": None,
                    }
                ],
            },
        )
