import json
import os

import responses
from django.urls import reverse

from .. import TestAdminMixin, TestLociMixin


class BaseTestAdmin(TestAdminMixin, TestLociMixin):
    geocode_url = 'https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/'

    def test_location_list(self):
        self._login_as_admin()
        self._create_location(name='test-admin-location-1')
        url = reverse('{0}_location_changelist'.format(self.url_prefix))
        r = self.client.get(url)
        self.assertContains(r, 'test-admin-location-1')

    def test_floorplan_list(self):
        self._login_as_admin()
        self._create_floorplan()
        self._create_location()
        url = reverse('{0}_floorplan_changelist'.format(self.url_prefix))
        r = self.client.get(url)
        self.assertContains(r, '1st floor')

    def test_location_json_view(self):
        self._login_as_admin()
        loc = self._create_location()
        r = self.client.get(reverse('admin:django_loci_location_json', args=[loc.pk]))
        expected = {
            'name': loc.name,
            'address': loc.address,
            'type': loc.type,
            'is_mobile': loc.is_mobile,
            'geometry': json.loads(loc.geometry.json),
        }
        self.assertDictEqual(r.json(), expected)

    def test_location_floorplan_json_view(self):
        self._login_as_admin()
        fl = self._create_floorplan()
        r = self.client.get(
            reverse('admin:django_loci_location_floorplans_json', args=[fl.location.pk])
        )
        expected = {
            'choices': [
                {
                    'id': str(fl.pk),
                    'str': str(fl),
                    'floor': fl.floor,
                    'image': fl.image.url,
                    'image_width': fl.image.width,
                    'image_height': fl.image.height,
                }
            ]
        }
        self.assertDictEqual(r.json(), expected)

    def test_location_change_image_removed(self):
        self._login_as_admin()
        loc = self._create_location(name='test-admin-location-1', type='indoor')
        fl = self._create_floorplan(location=loc)
        # remove floorplan image
        os.remove(fl.image.path)
        url = reverse('{0}_location_change'.format(self.url_prefix), args=[loc.pk])
        r = self.client.get(url)
        self.assertContains(r, 'test-admin-location-1')

    def test_floorplan_change_image_removed(self):
        self._login_as_admin()
        loc = self._create_location(name='test-admin-location-1', type='indoor')
        fl = self._create_floorplan(location=loc)
        # remove floorplan image
        os.remove(fl.image.path)
        url = reverse('{0}_floorplan_change'.format(self.url_prefix), args=[fl.pk])
        r = self.client.get(url)
        self.assertContains(r, 'test-admin-location-1')

    def test_is_mobile_location_json_view(self):
        self._login_as_admin()
        loc = self._create_location(is_mobile=True, geometry=None)
        response = self.client.get(
            reverse('admin:django_loci_location_json', args=[loc.pk])
        )
        self.assertEqual(response.status_code, 200)
        content = json.loads(response.content)
        self.assertEqual(content['geometry'], None)
        loc1 = self._create_location(
            name='location2', address='loc2 add', type='outdoor'
        )
        response1 = self.client.get(
            reverse('admin:django_loci_location_json', args=[loc1.pk])
        )
        self.assertEqual(response1.status_code, 200)
        content1 = json.loads(response1.content)
        expected = {
            'name': 'location2',
            'address': 'loc2 add',
            'type': 'outdoor',
            'is_mobile': False,
            'geometry': {'type': 'Point', 'coordinates': [12.512124, 41.898903]},
        }
        self.assertEqual(content1, expected)

    @responses.activate
    def test_geocode(self):
        self._login_as_admin()
        address = 'Red Square'
        url = '{0}?address={1}'.format(
            reverse('admin:django_loci_location_geocode_api'), address
        )
        # Mock HTTP request to the URL to work offline
        responses.add(
            responses.GET,
            f'{self.geocode_url}findAddressCandidates?singleLine=Red+Square&f=json&maxLocations=1',
            body=self._load_content('base/static/test-geocode.json'),
            content_type='application/json',
        )
        response = self.client.get(url)
        response_lat = round(response.json()['lat'])
        response_lng = round(response.json()['lng'])
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response_lat, 56)
        self.assertEqual(response_lng, 38)

    def test_geocode_no_address(self):
        self._login_as_admin()
        url = reverse('admin:django_loci_location_geocode_api')
        response = self.client.get(url)
        expected = {'error': 'Address parameter not defined'}
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response.json(), expected)

    @responses.activate
    def test_geocode_invalid_address(self):
        self._login_as_admin()
        invalid_address = 'thisaddressisnotvalid123abc'
        url = '{0}?address={1}'.format(
            reverse('admin:django_loci_location_geocode_api'), invalid_address
        )
        responses.add(
            responses.GET,
            f'{self.geocode_url}findAddressCandidates?singleLine=thisaddressisnotvalid123abc'
            '&f=json&maxLocations=1',
            body=self._load_content('base/static/test-geocode-invalid-address.json'),
            content_type='application/json',
        )
        response = self.client.get(url)
        expected = {'error': 'Not found location with given name'}
        self.assertEqual(response.status_code, 404)
        self.assertEqual(response.json(), expected)

    @responses.activate
    def test_reverse_geocode(self):
        self._login_as_admin()
        lat = 52
        lng = 21
        url = '{0}?lat={1}&lng={2}'.format(
            reverse('admin:django_loci_location_reverse_geocode_api'), lat, lng
        )
        # Mock HTTP request to the URL to work offline
        responses.add(
            responses.GET,
            f'{self.geocode_url}reverseGeocode?location=21.0%2C52.0&f=json&outSR=4326',
            body=self._load_content('base/static/test-reverse-geocode.json'),
            content_type='application/json',
        )
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'POL')

    @responses.activate
    def test_reverse_location_with_no_address(self):
        self._login_as_admin()
        lat = -30
        lng = -30
        url = '{0}?lat={1}&lng={2}'.format(
            reverse('admin:django_loci_location_reverse_geocode_api'), lat, lng
        )
        responses.add(
            responses.GET,
            f'{self.geocode_url}reverseGeocode?location=-30.0%2C-30.0&f=json&outSR=4326',
            body=self._load_content(
                'base/static/test-reverse-location-with-no-address.json'
            ),
            content_type='application/json',
        )
        response = self.client.get(url)
        response_address = response.json()['address']
        self.assertEqual(response.status_code, 404)
        self.assertEqual(response_address, '')

    def test_reverse_geocode_no_coords(self):
        self._login_as_admin()
        url = reverse('admin:django_loci_location_reverse_geocode_api')
        response = self.client.get(url)
        expected = {'error': 'lat or lng parameter not defined'}
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response.json(), expected)

[((66, 8, 66, 32), 'os.remove', 'os.remove', ({(66, 18, 66, 31): 'fl.image.path'}, {}), '(fl.image.path)', False, 'import os\n'), ((76, 8, 76, 32), 'os.remove', 'os.remove', ({(76, 18, 76, 31): 'fl.image.path'}, {}), '(fl.image.path)', False, 'import os\n'), ((88, 18, 88, 46), 'json.loads', 'json.loads', ({(88, 29, 88, 45): 'response.content'}, {}), '(response.content)', False, 'import json\n'), ((97, 19, 97, 48), 'json.loads', 'json.loads', ({(97, 30, 97, 47): 'response1.content'}, {}), '(response1.content)', False, 'import json\n'), ((130, 14, 130, 63), 'django.urls.reverse', 'reverse', ({(130, 22, 130, 62): '"""admin:django_loci_location_geocode_api"""'}, {}), "('admin:django_loci_location_geocode_api')", False, 'from django.urls import reverse\n'), ((197, 14, 197, 71), 'django.urls.reverse', 'reverse', ({(197, 22, 197, 70): '"""admin:django_loci_location_reverse_geocode_api"""'}, {}), "('admin:django_loci_location_reverse_geocode_api')", False, 'from django.urls import reverse\n'), ((31, 28, 31, 85), 'django.urls.reverse', 'reverse', (), '', False, 'from django.urls import reverse\n'), ((37, 24, 37, 53), 'json.loads', 'json.loads', ({(37, 35, 37, 52): 'loc.geometry.json'}, {}), '(loc.geometry.json)', False, 'import json\n'), ((45, 12, 45, 88), 'django.urls.reverse', 'reverse', (), '', False, 'from django.urls import reverse\n'), ((85, 12, 85, 69), 'django.urls.reverse', 'reverse', (), '', False, 'from django.urls import reverse\n'), ((94, 12, 94, 70), 'django.urls.reverse', 'reverse', (), '', False, 'from django.urls import reverse\n'), ((112, 12, 112, 61), 'django.urls.reverse', 'reverse', ({(112, 20, 112, 60): '"""admin:django_loci_location_geocode_api"""'}, {}), "('admin:django_loci_location_geocode_api')", False, 'from django.urls import reverse\n'), ((141, 12, 141, 61), 'django.urls.reverse', 'reverse', ({(141, 20, 141, 60): '"""admin:django_loci_location_geocode_api"""'}, {}), "('admin:django_loci_location_geocode_api')", False, 'from django.urls import reverse\n'), ((161, 12, 161, 69), 'django.urls.reverse', 'reverse', ({(161, 20, 161, 68): '"""admin:django_loci_location_reverse_geocode_api"""'}, {}), "('admin:django_loci_location_reverse_geocode_api')", False, 'from django.urls import reverse\n'), ((180, 12, 180, 69), 'django.urls.reverse', 'reverse', ({(180, 20, 180, 68): '"""admin:django_loci_location_reverse_geocode_api"""'}, {}), "('admin:django_loci_location_reverse_geocode_api')", False, 'from django.urls import reverse\n')]