'Get bounds from the specified (parent) location and its ancestors.
This is used to validate lat, lon, and bounds for child locations.
Caution: This calls update_location_tree if the parent bounds are
not set. During prepopulate, update_location_tree is disabled,
so unless the parent contains its own bounds (i.e. they do not need
to be propagated down from its ancestors), this will not provide a
check on location nesting. Prepopulate data should be prepared to
be correct. A set of candidate prepopulate data can be tested by
importing after prepopulate is run.
@param parent: A location_id to provide bounds suitable
for validating child locations
@return: bounding box and parent location name, as a list:
[lat_min, lon_min, lat_max, lon_max, parent_name]
@ToDo: Support Polygons (separate function?)'

def get_parent_bounds(self, parent=None):

    table = current.s3db.gis_location
    db = current.db
    parent = db((table.id == parent)).select(table.id, table.level, table.name, table.parent, table.path, table.lon, table.lat, table.lon_min, table.lat_min, table.lon_max, table.lat_max).first()
    if ((parent.lon_min is None) or (parent.lon_max is None) or (parent.lat_min is None) or (parent.lat_max is None) or (parent.lon_min == parent.lon_max) or (parent.lat_min == parent.lat_max)):
        if (parent.level == 'L1'):
            if parent.parent:
                L0 = db((table.id == parent.parent)).select(table.name, table.lon_min, table.lat_min, table.lon_max, table.lat_max).first()
                return (L0.lat_min, L0.lon_min, L0.lat_max, L0.lon_max, L0.name)
        if parent.path:
            path = parent.path
        else:
            path = GIS.update_location_tree(dict(id=parent.id, level=parent.level))
        if path:
            path_list = map(int, path.split('/'))
            rows = db(table.id.belongs(path_list)).select(table.level, table.name, table.lat, table.lon, table.lon_min, table.lat_min, table.lon_max, table.lat_max, orderby=table.level)
            row_list = rows.as_list()
            row_list.reverse()
            ok = False
            for row in row_list:
                if ((row['lon_min'] is not None) and (row['lon_max'] is not None) and (row['lat_min'] is not None) and (row['lat_max'] is not None) and (row['lon'] != row['lon_min'] != row['lon_max']) and (row['lat'] != row['lat_min'] != row['lat_max'])):
                    ok = True
                    break
            if ok:
                return (row['lat_min'], row['lon_min'], row['lat_max'], row['lon_max'], row['name'])
    else:
        return (parent.lat_min, parent.lon_min, parent.lat_max, parent.lon_max, parent.name)
    config = GIS.get_config()
    if config:
        return (config.lat_min, config.lon_min, config.lat_max, config.lon_max, None)
    return ((-90), (-180), 90, 180, None)
