# Path: db/common/symbols.py
# class ShieldFactory(object):
# 
#     def __init__(self, *classes):
#         self.classes = [ globals()[cl] for cl in classes]
# 
#     def create(self, tags, region, level):
#         """ Create a new symbol object from the given set of tags
#             from a list of types.
#         """
#         for c in self.classes:
#             sym = c.create(tags, region, level)
#             if sym is not None:
#                 return sym
# 
#         return None
# 
#     def write(self, symbol, force=False):
#         symid = symbol.get_id()
# 
#         if CONFIG.symbol_outdir is not None:
#             symfn = os.path.join(CONFIG.symbol_outdir, "%s.svg" % symid)
#             if force or not os.path.isfile(symfn):
#                 symbol.write_image(symfn)
#                 self._mangle_svg(symfn)
# 
# 
#         return symid
# 
#     def create_write(self, tags, region, level, force=False):
#         """ Create a new symbol object and render a picture and
#             write it out.
#         """
#         sym = self.create(tags, region, level)
# 
#         if sym is None:
#             return None
# 
#         return self.write(sym, force)
# 
#     def _mangle_svg(self, filename):
#         try:
#             dom = parse(filename)
#         except ExpatError:
#             print("WARNING: cannot parse", filename)
#             return
# 
#         for svg in dom.getElementsByTagName("svg"):
#             sym_ele = svg.getElementsByTagName("symbol")
#             use_ele = svg.getElementsByTagName("use")
# 
#             if sym_ele.length == 0 or use_ele.length == 0:
#                 continue
# 
#             symbols = {}
#             for e in sym_ele:
#                 symbols['#' + e.getAttribute('id')] = e.cloneNode(True)
#                 e.parentNode.removeChild(e)
# 
#             for e in use_ele:
#                 ref = e.getAttribute('xlink:href')
#                 x   = float(e.getAttribute('x'))
#                 y   = float(e.getAttribute('y'))
# 
#                 group = dom.createElement('g')
# 
#                 for ce in symbols[ref].childNodes:
#                     node = ce.cloneNode(True)
# 
#                     if node.nodeName == 'path':
#                         path = node.getAttribute('d')
# 
#                         newpath = ''
#                         is_x = True
#                         for p in path.split():
#                             if not p:
#                                 continue
# 
#                             if p[0].isupper():
#                                 dx = x
#                                 dy = y
#                                 newpath += p + ' '
#                             elif p[0].islower():
#                                 dx = 0
#                                 dy = 0
#                                 newpath += p + ' '
#                             elif p[0].isnumeric:
#                                 val = float(p) + (dx if is_x else dy)
#                                 is_x = not is_x
#                                 newpath += "%f " % val
# 
#                         node.setAttribute('d', newpath)
# 
#                     group.appendChild(node)
# 
#                 e.parentNode.replaceChild(group, e)
# 
#         with open(filename, 'w') as of:
#             dom.writexml(of)
# 
# Path: db/common/route_types.py
# class Network(Enum):
#     """ Basic types of network levels.
#     """
#     LOC = 0
#     REG = 1
#     NAT = 2
#     INT = 3
# 
#     def __call__(self, importance=0):
#         if abs(importance) > 3:
#             raise Runtime_error("Network importance must be between -3 and 3")
#         return 7 * self.value + 3 + importance
# 
#     def max(self):
#         return self.__call__(3)
# 
#     def min(self):
#         return self.__call__(-3)
# 
#     @staticmethod
#     def from_int(i):
#         if i <= Network.LOC.max():
#             return Network.LOC
#         if i <= Network.REG.max():
#             return Network.REG
#         if i <= Network.NAT.max():
#             return Network.NAT
#         if i <= Network.INT.max():
#             return Network.INT
#         raise ValueError("Integer out of range for Network")
# 
# Path: db/configs.py
# class RouteTableConfig(object):
#     table_name = 'routes'
# 
#     network_map = {}
#     tag_filter = None
#     symbols = None


import logging
import sqlalchemy as sa
from osgende.common.table import TableSource
from osgende.common.sqlalchemy import DropIndexIfExists, CreateTableAs
from osgende.common.threads import ThreadableDBObject
from osgende.common.tags import TagStore
from osgende.common.build_geometry import build_route_geometry
from shapely.ops import linemerge
from db.common.symbols import ShieldFactory
from db.common.route_types import Network
from db.configs import RouteTableConfig
from db import conf
from sqlalchemy.sql import functions as saf
from sqlalchemy.dialects.postgresql import JSONB
from geoalchemy2 import Geometry
from geoalchemy2.shape import from_shape

log = logging.getLogger(__name__)

ROUTE_CONF = conf.get('ROUTES', RouteTableConfig)

class RouteRow(dict):
    fields = set(('id', 'intnames', 'name', 'level', 'ref', 'itinary', 'network', 'top', 'geom', 'symbol', 'country'))

    def __init__(self, id_):
        for attr in self.fields:
            self[attr] = None

        self['id'] = id_
        self['intnames'] = {}
        self['level'] = Network.LOC()

    def __getattr__(self, name):
        return self[name]

    def __setattr__(self, name, value):
        if name not in self.fields:
            raise ValueError("Bad field " + name)
        self[name] = value

def _compute_route_level(network):
    # Multi-modal routes might have multiple network tags
    for n in network.split(';'):
        if n in ROUTE_CONF.network_map:
            return ROUTE_CONF.network_map[n]


# Path: db/common/symbols.py
# class ShieldFactory(object):
# 
#     def __init__(self, *classes):
#         self.classes = [ globals()[cl] for cl in classes]
# 
#     def create(self, tags, region, level):
#         """ Create a new symbol object from the given set of tags
#             from a list of types.
#         """
#         for c in self.classes:
#             sym = c.create(tags, region, level)
#             if sym is not None:
#                 return sym
# 
#         return None
# 
#     def write(self, symbol, force=False):
#         symid = symbol.get_id()
# 
#         if CONFIG.symbol_outdir is not None:
#             symfn = os.path.join(CONFIG.symbol_outdir, "%s.svg" % symid)
#             if force or not os.path.isfile(symfn):
#                 symbol.write_image(symfn)
#                 self._mangle_svg(symfn)
# 
# 
#         return symid
# 
#     def create_write(self, tags, region, level, force=False):
#         """ Create a new symbol object and render a picture and
#             write it out.
#         """
#         sym = self.create(tags, region, level)
# 
#         if sym is None:
#             return None
# 
#         return self.write(sym, force)
# 
#     def _mangle_svg(self, filename):
#         try:
#             dom = parse(filename)
#         except ExpatError:
#             print("WARNING: cannot parse", filename)
#             return
# 
#         for svg in dom.getElementsByTagName("svg"):
#             sym_ele = svg.getElementsByTagName("symbol")
#             use_ele = svg.getElementsByTagName("use")
# 
#             if sym_ele.length == 0 or use_ele.length == 0:
#                 continue
# 
#             symbols = {}
#             for e in sym_ele:
#                 symbols['#' + e.getAttribute('id')] = e.cloneNode(True)
#                 e.parentNode.removeChild(e)
# 
#             for e in use_ele:
#                 ref = e.getAttribute('xlink:href')
#                 x   = float(e.getAttribute('x'))
#                 y   = float(e.getAttribute('y'))
# 
#                 group = dom.createElement('g')
# 
#                 for ce in symbols[ref].childNodes:
#                     node = ce.cloneNode(True)
# 
#                     if node.nodeName == 'path':
#                         path = node.getAttribute('d')
# 
#                         newpath = ''
#                         is_x = True
#                         for p in path.split():
#                             if not p:
#                                 continue
# 
#                             if p[0].isupper():
#                                 dx = x
#                                 dy = y
#                                 newpath += p + ' '
#                             elif p[0].islower():
#                                 dx = 0
#                                 dy = 0
#                                 newpath += p + ' '
#                             elif p[0].isnumeric:
#                                 val = float(p) + (dx if is_x else dy)
#                                 is_x = not is_x
#                                 newpath += "%f " % val
# 
#                         node.setAttribute('d', newpath)
# 
#                     group.appendChild(node)
# 
#                 e.parentNode.replaceChild(group, e)
# 
#         with open(filename, 'w') as of:
#             dom.writexml(of)
# 
# Path: db/common/route_types.py
# class Network(Enum):
#     """ Basic types of network levels.
#     """
#     LOC = 0
#     REG = 1
#     NAT = 2
#     INT = 3
# 
#     def __call__(self, importance=0):
#         if abs(importance) > 3:
#             raise Runtime_error("Network importance must be between -3 and 3")
#         return 7 * self.value + 3 + importance
# 
#     def max(self):
#         return self.__call__(3)
# 
#     def min(self):
#         return self.__call__(-3)
# 
#     @staticmethod
#     def from_int(i):
#         if i <= Network.LOC.max():
#             return Network.LOC
#         if i <= Network.REG.max():
#             return Network.REG
#         if i <= Network.NAT.max():
#             return Network.NAT
#         if i <= Network.INT.max():
#             return Network.INT
#         raise ValueError("Integer out of range for Network")
# 
# Path: db/configs.py
# class RouteTableConfig(object):
#     table_name = 'routes'
# 
#     network_map = {}
#     tag_filter = None
#     symbols = None


# Path: db/tables/routes.py
import logging
import sqlalchemy as sa
from osgende.common.table import TableSource
from osgende.common.sqlalchemy import DropIndexIfExists, CreateTableAs
from osgende.common.threads import ThreadableDBObject
from osgende.common.tags import TagStore
from osgende.common.build_geometry import build_route_geometry
from shapely.ops import linemerge
from db.common.symbols import ShieldFactory
from db.common.route_types import Network
from db.configs import RouteTableConfig
from db import conf
from sqlalchemy.sql import functions as saf
from sqlalchemy.dialects.postgresql import JSONB
from geoalchemy2 import Geometry
from geoalchemy2.shape import from_shape


log = logging.getLogger(__name__)

ROUTE_CONF = conf.get('ROUTES', RouteTableConfig)

class RouteRow(dict):
    fields = set(('id', 'intnames', 'name', 'level', 'ref', 'itinary', 'network', 'top', 'geom', 'symbol', 'country'))

    def __init__(self, id_):
        for attr in self.fields:
            self[attr] = None

        self['id'] = id_
        self['intnames'] = {}
        self['level'] = Network.LOC()

    def __getattr__(self, name):
        return self[name]

    def __setattr__(self, name, value):
        if name not in self.fields:
            raise ValueError("Bad field " + name)
        self[name] = value

def _compute_route_level(network):
    # Multi-modal routes might have multiple network tags
    for n in network.split(';'):
        if n in ROUTE_CONF.network_map:
            return ROUTE_CONF.network_map[n]


    return Network.LOC()