'Returns the locations, markers and popup tooltips for an XML export
e.g. Feature Layers or Search results (Feature Resources)
e.g. Exports in KML, GeoRSS or GPX format
Called by S3REST: S3Resource.export_tree()
@param: resource - S3Resource instance (required)
@param: attr_fields - list of attr_fields to use instead of reading
from get_vars or looking up in gis_layer_feature
@param: count - total number of features
(can actually be more if features have multiple locations)'

@staticmethod
def get_location_data(resource, attr_fields=None, count=None):

    tablename = resource.tablename
    if (tablename == 'gis_feature_query'):
        return {}
    format = current.auth.permission.format
    geojson = (format == 'geojson')
    if geojson:
        if (count and (count > current.deployment_settings.get_gis_max_features())):
            headers = {'Content-Type': 'application/json'}
            message = 'Too    Many    Records'
            status = 509
            raise HTTP(status, body=current.xml.json_message(success=False, statuscode=status, message=message), web2py_error=message, **headers)
        if ((len(tablename) > 19) and tablename.startswith('gis_layer_shapefile')):
            location_data = (GIS.get_shapefile_geojson(resource) or {})
            return location_data
        elif (tablename == 'gis_theme_data'):
            location_data = (GIS.get_theme_geojson(resource) or {})
            return location_data
        else:
            pass
    elif (format in ('georss', 'kml', 'gpx')):
        pass
    else:
        return {}
    NONE = current.messages['NONE']
    db = current.db
    s3db = current.s3db
    request = current.request
    get_vars = request.get_vars
    ftable = s3db.gis_layer_feature
    layer = None
    layer_id = get_vars.get('layer', None)
    if layer_id:
        layer = db((ftable.layer_id == layer_id)).select(ftable.attr_fields, ftable.popup_fields, ftable.individual, ftable.points, ftable.trackable, limitby=(0, 1)).first()
    else:
        controller = request.controller
        function = request.function
        query = ((ftable.controller == controller) & (ftable.function == function))
        layers = db(query).select(ftable.layer_id, ftable.attr_fields, ftable.popup_fields, ftable.style_default, ftable.individual, ftable.points, ftable.trackable)
        if (len(layers) > 1):
            layers.exclude((lambda row: (row.style_default == False)))
            if (len(layers) > 1):
                return None
        if layers:
            layer = layers.first()
            layer_id = layer.layer_id
    if (not attr_fields):
        attr_fields = get_vars.get('attr', [])
    if attr_fields:
        attr_fields = attr_fields.split(',')
    popup_fields = get_vars.get('popup', [])
    if popup_fields:
        popup_fields = popup_fields.split(',')
    if layer:
        if (not popup_fields):
            popup_fields = (layer.popup_fields or [])
        if (not attr_fields):
            attr_fields = (layer.attr_fields or [])
        individual = layer.individual
        points = layer.points
        trackable = layer.trackable
    else:
        if (not popup_fields):
            popup_fields = ['name']
        individual = False
        points = False
        trackable = False
    table = resource.table
    pkey = table._id.name
    attributes = {}
    markers = {}
    styles = {}
    _pkey = table[pkey]
    _pkey.represent = None
    if geojson:
        if popup_fields:
            attr_fields = list(set((popup_fields + attr_fields)))
        if attr_fields:
            attr = {}
            fields = list(attr_fields)
            if (pkey not in fields):
                fields.insert(0, pkey)
            data = resource.select(fields, limit=None, raw_data=True, represent=True, show_links=False)
            attr_cols = {}
            for f in data['rfields']:
                fname = f.fname
                selector = f.selector
                if ((fname in attr_fields) or (selector in attr_fields)):
                    fieldname = f.colname
                    (tname, fname) = fieldname.split('.')
                    try:
                        ftype = db[tname][fname].type
                    except AttributeError:
                        ftype = None
                    except KeyError:
                        from s3utils import s3_debug
                        s3_debug('SGIS', ("Field    %s    doesn't    exist    in    table    %s" % (fname, tname)))
                        continue
                    attr_cols[fieldname] = (ftype, fname)
            _pkey = str(_pkey)
            for row in data['rows']:
                record_id = int(row[_pkey])
                if attr_cols:
                    attribute = {}
                    for fieldname in attr_cols:
                        represent = row[fieldname]
                        if ((represent is not None) and (represent not in (NONE, ''))):
                            _attr = attr_cols[fieldname]
                            ftype = _attr[0]
                            if (ftype == 'integer'):
                                if isinstance(represent, lazyT):
                                    represent = s3_unicode(represent)
                                else:
                                    represent = row['_row'][fieldname]
                            elif (ftype in ('double', 'float')):
                                represent = row['_row'][fieldname]
                            else:
                                represent = s3_unicode(represent)
                            attribute[_attr[1]] = represent
                    attr[record_id] = attribute
            attributes[tablename] = attr
        _markers = get_vars.get('markers', None)
        if _markers:
            marker_fn = s3db.get_config(tablename, 'marker_fn')
            if marker_fn:
                m = {}
                for record in resource:
                    m[record[pkey]] = marker_fn(record)
            else:
                (c, f) = tablename.split('_', 1)
                m = GIS.get_marker(c, f)
            markers[tablename] = m
        if individual:
            stable = s3db.gis_style
            query = (((stable.deleted == False) & (stable.layer_id == layer_id)) & stable.record_id.belongs(resource._ids))
            rows = db(query).select(stable.record_id, stable.style)
            for row in rows:
                styles[row.record_id] = json.dumps(row.style, separators=SEPARATORS)
            styles[tablename] = styles
    else:
        marker_fn = s3db.get_config(tablename, 'marker_fn')
        if marker_fn:
            for record in resource:
                markers[record[pkey]] = marker_fn(record)
        else:
            (c, f) = tablename.split('_', 1)
            markers = GIS.get_marker(c, f)
        markers[tablename] = markers
    latlons = {}
    geojsons = {}
    gtable = s3db.gis_location
    if trackable:
        ids = resource._ids
        ids.sort()
        try:
            tracker = S3Trackable(table, record_ids=ids)
        except SyntaxError:
            pass
        else:
            _latlons = tracker.get_location(_fields=[gtable.lat, gtable.lon], empty=False)
            index = 0
            for _id in ids:
                _location = _latlons[index]
                latlons[_id] = (_location.lat, _location.lon)
                index += 1
    if (not latlons):
        join = True
        if ('location_id' in table.fields):
            query = (table.id.belongs(resource._ids) & (table.location_id == gtable.id))
        elif ('site_id' in table.fields):
            stable = s3db.org_site
            query = ((table.id.belongs(resource._ids) & (table.site_id == stable.site_id)) & (stable.location_id == gtable.id))
        elif (tablename == 'gis_location'):
            join = False
            query = table.id.belongs(resource._ids)
        else:
            context = resource.get_config('context')
            if context:
                location_context = context.get('location')
            else:
                location_context = None
            if (not location_context):
                return None
            rfield = resource.resolve_selector(location_context)
            if ('.' in location_context):
                (alias, cfield) = location_context.split('.', 1)
                try:
                    component = resource.components[alias]
                except:
                    return None
                ctablename = component.tablename
                ctable = s3db[ctablename]
                query = ((table.id.belongs(resource._ids) & rfield.join[ctablename]) & (ctable[cfield] == gtable.id))
                resource.components = Storage()
            else:
                return None
        if (geojson and (not points)):
            geojsons[tablename] = GIS.get_locations(table, query, join, geojson)
        else:
            rows = db(query).select(table.id, gtable.lat, gtable.lon)
            if join:
                for row in rows:
                    _location = row['gis_location']
                    latlons[row[tablename].id] = (_location.lat, _location.lon)
            else:
                for row in rows:
                    latlons[row.id] = (row.lat, row.lon)
    _latlons = {}
    if latlons:
        _latlons[tablename] = latlons
    return dict(geojsons=geojsons, latlons=_latlons, attributes=attributes, markers=markers, styles=styles)
