"""
 Utilities for manipulating Geometry WKT.
"""

from django.utils import six


def precision_wkt(geom, prec):
    """
    Returns WKT text of the geometry according to the given precision (an
    integer or a string).  If the precision is an integer, then the decimal
    places of coordinates WKT will be truncated to that number:

     >>> from django.contrib.gis.geos import Point
     >>> pnt = Point(5, 23)
     >>> pnt.wkt
     'POINT (5.0000000000000000 23.0000000000000000)'
     >>> precision_wkt(pnt, 1)
     'POINT (5.0 23.0)'

    If the precision is a string, it must be valid Python format string
    (e.g., '%20.7f') -- thus, you should know what you're doing.
    """
    if isinstance(prec, int):
        num_fmt = '%%.%df' % prec
    elif isinstance(prec, six.string_types):
        num_fmt = prec
    else:
        raise TypeError

    # TODO: Support 3D geometries.
    coord_fmt = ' '.join([num_fmt, num_fmt])

    def formatted_coords(coords):
        return ','.join(coord_fmt % c[:2] for c in coords)

    def formatted_poly(poly):
        return ','.join('(%s)' % formatted_coords(r) for r in poly)

    def formatted_geom(g):
        gtype = str(g.geom_type).upper()
        yield '%s(' % gtype
        if gtype == 'POINT':
            yield formatted_coords((g.coords,))
        elif gtype in ('LINESTRING', 'LINEARRING'):
            yield formatted_coords(g.coords)
        elif gtype in ('POLYGON', 'MULTILINESTRING'):
            yield formatted_poly(g)
        elif gtype == 'MULTIPOINT':
            yield formatted_coords(g.coords)
        elif gtype == 'MULTIPOLYGON':
            yield ','.join('(%s)' % formatted_poly(p) for p in g)
        elif gtype == 'GEOMETRYCOLLECTION':
            yield ','.join(''.join(wkt for wkt in formatted_geom(child)) for child in g)
        else:
            raise TypeError
        yield ')'

    return ''.join(wkt for wkt in formatted_geom(geom))
