'Reads the specified GIS config from the DB, caches it in response.
Passing in a false or non-existent id will cause the personal config,
if any, to be used, else the site config (uuid SITE_DEFAULT), else
their fallback values defined in this class.
If force_update_cache is true, the config will be read and cached in
response even if the specified config is the same as what\'s already
cached. Used when the config was just written.
The config itself will be available in response.s3.gis.config.
Scalar fields from the gis_config record and its linked
gis_projection record have the same names as the fields in their
tables and can be accessed as response.s3.gis.<fieldname>.
Returns the id of the config it actually used, if any.
@param: config_id. use \'0\' to set the SITE_DEFAULT
@ToDo: Merge configs for Event'

@staticmethod
def set_config(config_id=None, force_update_cache=False):

    _gis = current.response.s3.gis
    if (config_id and (not force_update_cache) and _gis.config and (_gis.config.id == config_id)):
        return
    db = current.db
    s3db = current.s3db
    ctable = s3db.gis_config
    mtable = s3db.gis_marker
    ptable = s3db.gis_projection
    stable = s3db.gis_style
    fields = (ctable.id, ctable.default_location_id, ctable.region_location_id, ctable.geocoder, ctable.lat_min, ctable.lat_max, ctable.lon_min, ctable.lon_max, ctable.zoom, ctable.lat, ctable.lon, ctable.pe_id, ctable.wmsbrowser_url, ctable.wmsbrowser_name, ctable.zoom_levels, ctable.merge, mtable.image, mtable.height, mtable.width, ptable.epsg, ptable.proj4js, ptable.maxExtent, ptable.units)
    cache = Storage()
    row = None
    rows = None
    if config_id:
        query = ((ctable.id == config_id) | (ctable.uuid == 'SITE_DEFAULT'))
        left = (ptable.on((ptable.id == ctable.projection_id)), stable.on(((stable.config_id == ctable.id) & (stable.layer_id == None))), mtable.on((mtable.id == stable.marker_id)))
        rows = db(query).select(left=left, orderby=ctable.pe_type, limitby=(0, 2), *fields)
        if (len(rows) == 1):
            row = rows.first()
    elif (config_id is 0):
        query = (ctable.uuid == 'SITE_DEFAULT')
        left = (ptable.on((ptable.id == ctable.projection_id)), stable.on(((stable.config_id == ctable.id) & (stable.layer_id == None))), mtable.on((mtable.id == stable.marker_id)))
        row = db(query).select(left=left, limitby=(0, 1), *fields).first()
        if (not row):
            _gis.config = cache
            return cache
    if ((not rows) and (not row)):
        auth = current.auth
        if auth.is_logged_in():
            user = auth.user
            pe_id = user.get('pe_id')
            if pe_id:
                pes = []
                if user.organisation_id:
                    otable = s3db.org_organisation
                    org = db((otable.id == user.organisation_id)).select(otable.pe_id, limitby=(0, 1)).first()
                    try:
                        pes.append(org.pe_id)
                    except:
                        current.log.warning(('Unable    to    find    Org    %s' % user.organisation_id))
                    if current.deployment_settings.get_org_branches():
                        ancestors = s3db.pr_get_ancestors(org.pe_id)
                        pes += ancestors
                if user.site_id:
                    site_pe_id = s3db.pr_get_pe_id('org_site', user.site_id)
                    if site_pe_id:
                        pes.append(site_pe_id)
                if user.org_group_id:
                    ogtable = s3db.org_group
                    ogroup = db((ogtable.id == user.org_group_id)).select(ogtable.pe_id, limitby=(0, 1)).first()
                    pes = list(pes)
                    try:
                        pes.append(ogroup.pe_id)
                    except:
                        current.log.warning(('Unable    to    find    Org    Group    %s' % user.org_group_id))
                query = ((ctable.uuid == 'SITE_DEFAULT') | ((ctable.pe_id == pe_id) & (ctable.pe_default != False)))
                if (len(pes) == 1):
                    query |= (ctable.pe_id == pes[0])
                else:
                    query |= ctable.pe_id.belongs(pes)
                left = (ptable.on((ptable.id == ctable.projection_id)), stable.on(((stable.config_id == ctable.id) & (stable.layer_id == None))), mtable.on((mtable.id == stable.marker_id)))
                rows = db(query).select(left=left, orderby=ctable.pe_type, *fields)
                if (len(rows) == 1):
                    row = rows.first()
    if (rows and (not row)):
        merge = True
        cache['ids'] = []
        for row in rows:
            if (not merge):
                break
            config = row['gis_config']
            if (config.merge is False):
                merge = False
            if (not config_id):
                config_id = config.id
            cache['ids'].append(config.id)
            for key in config:
                if (key in ('delete_record', 'gis_layer_config', 'gis_menu', 'update_record', 'merge')):
                    continue
                if ((key not in cache) or (cache[key] is None)):
                    cache[key] = config[key]
            if (('epsg' not in cache) or (cache['epsg'] is None)):
                projection = row['gis_projection']
                for key in ['epsg', 'units', 'maxExtent', 'proj4js']:
                    cache[key] = (projection[key] if (key in projection) else None)
            if (('marker_image' not in cache) or (cache['marker_image'] is None)):
                marker = row['gis_marker']
                for key in ('image', 'height', 'width'):
                    cache[('marker_%s' % key)] = (marker[key] if (key in marker) else None)
        for key in ('epsg', 'units', 'proj4js', 'maxExtent', 'marker_image', 'marker_height', 'marker_width'):
            if (key not in cache):
                cache[key] = None
    if (not row):
        query = (((((ctable.uuid == 'SITE_DEFAULT') & (mtable.id == stable.marker_id)) & (stable.config_id == ctable.id)) & (stable.layer_id == None)) & (ptable.id == ctable.projection_id))
        row = db(query).select(limitby=(0, 1), *fields).first()
        if (not row):
            _gis.config = cache
            return cache
    if (not cache):
        config = row['gis_config']
        config_id = config.id
        cache['ids'] = [config_id]
        projection = row['gis_projection']
        marker = row['gis_marker']
        for key in config:
            cache[key] = config[key]
        for key in ('epsg', 'maxExtent', 'proj4js', 'units'):
            cache[key] = (projection[key] if (key in projection) else None)
        for key in ('image', 'height', 'width'):
            cache[('marker_%s' % key)] = (marker[key] if (key in marker) else None)
    _gis.config = cache
    return cache
