#########################################################################
#
# Copyright (C) 2012 OpenPlans
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#########################################################################

import os
import math
from django.test.client import Client
from django.test import TestCase
from django.core.urlresolvers import reverse

from geonode import GeoNodeException
from geonode.utils import forward_mercator, inverse_mercator

class GeoNodeSmokeTests(TestCase):

    fixtures = ['people_data.json']
    GEOSERVER = False

    def setUp(self):
        # If Geoserver and GeoNetwork are not running
        # avoid running tests that call those views.
        if "GEOSERVER" in os.environ.keys():
            self.GEOSERVER = True

    def tearDown(self):
        pass

    #### Basic Pages ####

    def test_home_page(self):
        '''Test if the homepage renders.'''
        c = Client()
        response = c.get(reverse('home'))
        self.failUnlessEqual(response.status_code, 200)

    def test_help_page(self):
        '''Test help page renders.'''

        c = Client()
        response = c.get(reverse('help'))
        self.failUnlessEqual(response.status_code, 200)

    def test_developer_page(self):
        '''Test help page renders.'''

        c = Client()
        response = c.get(reverse('help'))
        self.failUnlessEqual(response.status_code, 200)

    #### Layer Pages ####

    def test_layer_page(self):
        'Test if the data home page renders.'
        c = Client()
        response = c.get(reverse('layer_browse'))
        self.failUnlessEqual(response.status_code, 200)

    def test_layer_acls(self):
        'Test if the data/acls endpoint renders.'
        c = Client()
        response = c.get(reverse('layer_acls'))
        self.failUnlessEqual(response.status_code, 200)

    #### Maps Pages ####

    def test_maps_page(self):
        '''Test Maps page renders.'''

        c = Client()
        response = c.get(reverse('maps_browse'))
        self.failUnlessEqual(response.status_code, 200)

    def test_new_map_page(self):
        '''Test New Map page renders.'''

        c = Client()
        response = c.get(reverse('new_map'))
        self.failUnlessEqual(response.status_code, 200)

    #### People Pages ####

    def test_profiles(self):
        '''Test the profiles page renders.'''

        c = Client()
        response = c.get(reverse('profile_list'))
        self.failUnlessEqual(response.status_code, 200)

    def test_profiles(self):
        '''Test that user profile pages render.'''
        c = Client()
        response = c.get(reverse('profile_detail', args=['admin']))
        self.failUnlessEqual(response.status_code, 200)
        response = c.get(reverse('profile_detail', args=['norman']))
        self.failUnlessEqual(response.status_code, 200)


class GeoNodeUtilsTests(TestCase):

    def setUp(self):
        pass

    def tearDown(self):
        pass

    ### Some other Stuff

    """
    def test_check_geonode_is_up(self):
        from contextlib import nested
        from geonode.utils import check_geonode_is_up

        def blowup():
            raise Exception("BOOM")

        with patch('geonode.maps.models.gs_catalog') as mock_gs:
            mock_gs.get_workspaces.side_effect = blowup

            self.assertRaises(GeoNodeException, check_geonode_is_up)

        with nested(
            patch('geonode.maps.models.gs_catalog'),
            patch('geonode.maps.models.Layer.objects.geonetwork')
        ) as (mock_gs, mock_gn):
            mock_gn.login.side_effect = blowup
            self.assertRaises(GeoNodeException, check_geonode_is_up)
            self.assertTrue(mock_gs.get_workspaces.called)

        with nested(
            patch('geonode.maps.models.gs_catalog'),
            patch('geonode.maps.models.Layer.objects.geonetwork')
        ) as (mock_gs, mock_gn):
            # no assertion, this should just run without error
            check_geonode_is_up()
    """

    def test_forward_mercator(self):
        arctic = forward_mercator((0, 85))
        antarctic = forward_mercator((0, -85))
        hawaii = forward_mercator((-180, 0))
        phillipines = forward_mercator((180, 0))
        ne = forward_mercator((180, 90))
        sw = forward_mercator((-180, -90))

        inf_test = forward_mercator(
            (-8.988465674311579e+307, -8.988465674311579e+307)
        )

        self.assertEqual(inf_test[0], float('-inf'))
        self.assertEqual(inf_test[1], float('-inf'))

        self.assertEqual(round(arctic[0]), 0, "Arctic longitude is correct")
        self.assertEqual(round(arctic[1]), 19971869, "Arctic latitude is correct")

        self.assertEqual(round(antarctic[0]), 0, "Antarctic longitude is correct")
        self.assertEqual(round(antarctic[1]), -19971869, "Antarctic latitude is correct")

        self.assertEqual(round(hawaii[0]), -20037508, "Hawaiian lon is correct")
        self.assertEqual(round(hawaii[1]), 0, "Hawaiian lat is correct")

        self.assertEqual(round(phillipines[0]), 20037508, "Phillipines lon is correct")
        self.assertEqual(round(phillipines[1]), 0, "Phillipines lat is correct")

        self.assertEqual(round(ne[0]), 20037508, "NE lon is correct")
        self.assertTrue(ne[1] > 50000000, "NE lat is correct")

        self.assertEqual(round(sw[0]), -20037508, "SW lon is correct")
        self.assertTrue(math.isinf(sw[1]), "SW lat is correct")

        # verify behavior for invalid y values
        self.assertEqual(float('-inf'), forward_mercator((0, 135))[1])
        self.assertEqual(float('-inf'), forward_mercator((0, -135))[1])

    def test_inverse_mercator(self):
        arctic = inverse_mercator(forward_mercator((0, 85)))
        antarctic = inverse_mercator(forward_mercator((0, -85)))
        hawaii = inverse_mercator(forward_mercator((-180, 0)))
        phillipines = inverse_mercator(forward_mercator((180, 0)))
        ne = inverse_mercator(forward_mercator((180, 90)))
        sw = inverse_mercator(forward_mercator((-180, -90)))

        self.assertAlmostEqual(arctic[0], 0.0, msg="Arctic longitude is correct")
        self.assertAlmostEqual(arctic[1], 85.0, msg="Arctic latitude is correct")

        self.assertAlmostEqual(antarctic[0], 0.0, msg="Antarctic longitude is correct")
        self.assertAlmostEqual(antarctic[1], -85.0, msg="Antarctic latitude is correct")

        self.assertAlmostEqual(hawaii[0], -180.0, msg="Hawaiian lon is correct")
        self.assertAlmostEqual(hawaii[1], 0.0, msg="Hawaiian lat is correct")

        self.assertAlmostEqual(phillipines[0], 180.0, msg="Phillipines lon is correct")
        self.assertAlmostEqual(phillipines[1], 0.0, msg="Phillipines lat is correct")

        self.assertAlmostEqual(ne[0], 180.0, msg="NE lon is correct")
        self.assertAlmostEqual(ne[1], 90.0, msg="NE lat is correct")

        self.assertAlmostEqual(sw[0], -180.0, msg="SW lon is correct")
        self.assertAlmostEqual(sw[1], -90.0, msg="SW lat is correct")

    def test_split_query(self):
        query = 'alpha "beta gamma"   delta  '
        from geonode.utils import _split_query 
        keywords = _split_query(query)
        self.assertEqual(keywords[0], "alpha")
        self.assertEqual(keywords[1], "beta gamma")
        self.assertEqual(keywords[2], "delta")

class PermissionViewTests(TestCase):
    pass
