# Copyright (c) 2004 by Intevation GmbH
# Authors:
# Martin Schulze <joey@infodrom.org>
#
# This program is free software under the GPL (>=v2)
# Read the file COPYING coming with Thuban for details.

"""
Test for the PyOGCLib from Sean C. Gillies <sgillies@users.sourceforge.net>

http://www.sourceforge.net/projects/pyogclib

Requires the ogclib installed regularily on the system, accessible via
PYTHONPATH or checked out alongside the Thuban checkout.
"""

__version__ = "$Revision: 1.8 $"
# $Source: /thubanrepository/thuban/Extensions/wms/test/test_ogclib.py,v $
# $Id: test_ogclib.py,v 1.8 2004/11/30 16:56:50 joey Exp $

import os
import unittest

from string import split
from sys import path

from adjustpath import thubandir
path.insert(0, thubandir + "/test")

import support

# ----------------------------------------------------------------------
# FIXME: Temporary code until PyOGCLib is a standard requirement

from sys import path

# Assume the PyOGCLib to be checked out next to the thuban main directory
# setting PYTHONPATH accordingly is fine as well
#
pyogclib = os.path.abspath(thubandir + "/../PyOGCLib")
if os.path.isdir(pyogclib) and os.path.isdir(pyogclib + "/ogclib"):
    path.insert(0, pyogclib)
# ----------------------------------------------------------------------

_pyogclib_import_error = None
try:
    from ogclib.WMSClient import WMSClient
except ImportError, extra:
    _pyogclib_import_error = str(extra)


class TestOGCLib(unittest.TestCase):
    """
    Defines a test environment for the PyOGCLib, i.e. check whether URL
    strings are built properly.
    """

    wmsclient = None

    def setUp(self):
        skip_if_no_ogclib()
        self.wmsclient = WMSClient()

    def compare_URLs(self, foo, bar):
        """
        Check if two URLs are equal, i.e.:
        - check for same base URL
        - check same number of HTTP GET arguments
        - check whether all arguments from one URL also exist in the second
        """

        foo_tuple = split(foo, "?")
        bar_tuple = split(bar, "?")

        # Check for same base URL
        if foo_tuple[0] != bar_tuple[0]:
            self.fail("%s != %s" %(foo_tuple[0], bar_tuple[0]))

        # Check for same length of entire HTTP GET argument string
        if len(foo_tuple) != len(bar_tuple):
            self.fail("One URL has no arguments");

        # Loop through all HTTP GET arguments for existance
        if len(foo_tuple) > 1 and len(bar_tuple) > 1:
            foo_opts = split(foo_tuple[1], "&")
            bar_opts = split(bar_tuple[1], "&")

            if len(foo_opts) != len(bar_opts):
                self.fail("Different number of arguments");

            for part in foo_opts:
                if part not in bar_opts:
                    self.fail("%s not in second argument list" % part);


    def test_compareURLs(self):
        """Perform some tests for own compare routine"""

        # Compare same base URL
        result = "http://frida.intevation.org/cgi-bin"
        self.compare_URLs("http://frida.intevation.org/cgi-bin", result)

        # Compare different base URL with same length
        self.assertRaises(AssertionError, self.compare_URLs, "http://frida.intevation.org/cgi-lib", result)

        # Compare same bse with one argument
        result = "http://frida.intevation.org/cgi-bin?foo=eins"
        self.compare_URLs("http://frida.intevation.org/cgi-bin?foo=eins", result)

        # Compare same base URL differnt first argument
        self.assertRaises(AssertionError, self.compare_URLs, "http://frida.intevation.org/cgi-bin?bar=eins", result)

        # Compare same base with two arguments
        result = "http://frida.intevation.org/cgi-bin?foo=eins&bar=zwei"
        self.compare_URLs("http://frida.intevation.org/cgi-bin?foo=eins&bar=zwei", result)
        self.compare_URLs("http://frida.intevation.org/cgi-bin?bar=zwei&foo=eins", result)

        # Compare same base with different two arguments
        self.assertRaises(AssertionError, self.compare_URLs, "http://frida.intevation.org/cgi-bin?foo=zwei&bar=eins", result)

        # Compare same base with three arguments
        result = "http://frida.intevation.org/cgi-bin?foo=eins&bar=zwei&baz=jan&quux=tux"
        self.compare_URLs("http://frida.intevation.org/cgi-bin?foo=eins&bar=zwei&baz=jan&quux=tux", result)
        self.compare_URLs("http://frida.intevation.org/cgi-bin?baz=jan&bar=zwei&quux=tux&foo=eins", result)

        # Compare same base with different three arguments
        testurl = "http://frida.intevation.org/cgi-bin?baz=jan&foo=zwei&quux=tux&bar=eins"
        self.assertRaises(AssertionError, self.compare_URLs, testurl, result)


    def test_CapabilityURL(self):
        """Test the getCapabilitiesURL() method"""

        frida = "http://frida.intevation.org/cgi-bin/frida_wms?"

        url = self.wmsclient.getCapabilitiesURL(frida, "1.0")
        result = frida + "WMTVER=1.0&REQUEST=capabilities"
        self.compare_URLs(url, result)

        url = self.wmsclient.getCapabilitiesURL(frida, "1.1")
        result = frida + "VERSION=1.1&SERVICE=WMS&REQUEST=GetCapabilities"
        self.compare_URLs(url, result)


    def test_GetMapURL(self):
        """Test the getMapURL() method"""

        frida = "http://frida.intevation.org/cgi-bin/frida_wms?"

        format = 'image/jpeg'
        format_enc = 'image%2Fjpeg'
        width = 400
        height = 350
        epsg = 4326
        bbox = {'minx': -107, 'miny': 40, 'maxx': -109, 'maxy': 41}
        layers = [ ]
        styles = [ ]
        version = '1.1'

        result_base = frida + "WMTVER=1.0&REQUEST=map" + \
                      "&FORMAT="+format_enc + \
                      "&SRS=EPSG%s%d" %("%3A", epsg) + \
                      "&BBOX=%f%s%f%s%f%s%f" %(bbox['minx'], "%2C", bbox['miny'], "%2C",
                                                bbox['maxx'], "%2C", bbox['maxy']) + \
                                                "&WIDTH=%s" % width + "&HEIGHT=%s" % height
        result = result_base + \
                 "&LAYERS=" + "%2C".join(layers) + \
                 "&STYLES=" + "%2C".join(styles)
        url = self.wmsclient.getMapURL(frida, format, width, height, epsg,
                             bbox, layers, version=version)

        # Repeat and continue with version 1.1, as denoted in OGC 01-068r3
        version = '1.1'
        result_base = frida + "VERSION=1.1&SERVICE=WMS&REQUEST=GetMap" + \
                      "&FORMAT="+format_enc + \
                      "&SRS=EPSG%s%d" %("%3A", epsg) + \
                      "&BBOX=%f%s%f%s%f%s%f" %(bbox['minx'], "%2C", bbox['miny'], "%2C",
                                                bbox['maxx'], "%2C", bbox['maxy']) + \
                                                "&WIDTH=%s" % width + "&HEIGHT=%s" % height
        result = result_base + \
                 "&LAYERS=" + "%2C".join(layers) + \
                 "&STYLES=" + "%2C".join(styles)
        url = self.wmsclient.getMapURL(frida, format, width, height, epsg,
                             bbox, layers, version=version)
        self.compare_URLs(result, url)

        result += "&TRANSPARENT=TRUE"
        url = self.wmsclient.getMapURL(frida, format, width, height, epsg,
                             bbox, layers, version=version,
                             transparent=1 )
        self.compare_URLs(result, url)

        result += "&BGCOLOR=0xFF00FF"
        url = self.wmsclient.getMapURL(frida, format, width, height, epsg,
                             bbox, layers, version=version,
                             transparent=1, bgcolor='0xFF00FF')
        self.compare_URLs(result, url)

        layers = [ 'foo' ]
        result = result_base + \
                 "&LAYERS=" + "%2C".join(layers) + \
                 "&STYLES=" + "%2C".join(styles)
        url = self.wmsclient.getMapURL(frida, format, width, height, epsg,
                             bbox, layers, version=version)
        self.compare_URLs(result, url)

        layers.append('bar')
        result = result_base + \
                 "&LAYERS=" + "%2C".join(layers) + \
                 "&STYLES=" + "%2C".join(styles)
        url = self.wmsclient.getMapURL(frida, format, width, height, epsg,
                             bbox, layers, version=version)
        self.compare_URLs(result, url)

        styles = [ 'something' ]
        result = result_base + \
                 "&LAYERS=" + "%2C".join(layers) + \
                 "&STYLES=" + "%2C".join(styles)
        url = self.wmsclient.getMapURL(frida, format, width, height, epsg,
                             bbox, layers, version=version,
                             styles = styles)
        self.compare_URLs(result, url)

        styles.append('else')
        result = result_base + \
                 "&LAYERS=" + "%2C".join(layers) + \
                 "&STYLES=" + "%2C".join(styles)
        url = self.wmsclient.getMapURL(frida, format, width, height, epsg,
                             bbox, layers, version=version,
                             styles = styles)
        self.compare_URLs(result, url)


def skip_if_no_ogclib():
    if _pyogclib_import_error is not None:
        raise support.SkipTest(_pyogclib_import_error)
#        raise support.SkipTest("No PyOGCLib found, hence no tests available.")


if __name__ == "__main__":
    support.run_tests()

"""

Additional notes:
    - Parameter names shall not be case sensitive, but parameter
      values shall be case sensitive. [OGC 01-068r3, 6.4.1, p13]

      This is not supported by the compare URL method, but may need to
      in the future.

    - Some geospatial inforamtion may be available at multiple times,
      like a whether map or satalite photo.  Capabilities may announce
      available times. [OGC 01-068r3, 6.5.7, p18]

      This is not yet supported by WMSClient

    - According to the specs a comma in LAYERS and STYLES list doesn't
      have to be encoded.  Maybe this could cause problems with some
      servers, just to keep in mind.

"""
