import csv, re, unicodedata, json, math, sys
S = sys.argv[1]
GEN = {'dam','dams','reservoir','reservoirs','lake','meer','damwal','the'}
def toks(t):
    t = unicodedata.normalize('NFKD', t or '').encode('ascii','ignore').decode().lower()
    t = re.sub(r'\(.*?\)', ' ', t)
    t = re.sub(r'dam\b', ' ', t)  # Vaaldam -> vaal
    w = [x for x in re.split(r'[^a-z0-9]+', t) if x and x not in GEN]
    return w
def keys(t):
    w = toks(t); return {''.join(w), ''.join(sorted(w))} - {''}
cands = list(csv.DictReader(open(f'{S}/cand.csv')))
def tags(s):
    return dict(re.findall(r'"([^"]+)"=>"((?:[^"\\]|\\.)*)"', s or ''))
for c in cands:
    tg = tags(c['other_tags']); c['tags'] = tg
    c['keys'] = keys(c['name'])
    for k2 in ('alt_name','old_name','name:en','name:af','official_name','loc_name','short_name'):
        if tg.get(k2): c['keys'] |= keys(tg[k2])
    c['provs'] = set((c['provs'] or '').split())
cands = [c for c in cands if c['src']=='d' or c['tags'].get('water') not in ('river','stream','canal','oxbow','riverbank','wastewater','pond') or 'dam' in (c['name'] or '').lower()]
dws = list(csv.reader(open(f'{S}/dws.csv')))
def dist(a, b):  # km
    return math.hypot((a[0]-b[0])*111*math.cos(math.radians(a[1])), (a[1]-b[1])*111)
out = []
for st, dam, river, country, provs, cap in dws:
    P = set(provs.split()); k = keys(dam)
    def ok(c):
        if c['provs'] and P: return bool(c['provs'] & P)
        if not c['provs']: return country in ('LS','SZ') or not P
        return not P  # SA polygon for a dam DWS gives no province (Glen Melville)
    m = [c for c in cands if c['keys'] & k and ok(c)]
    if not m:  # a looser key: one name inside the other, long enough
        m = [c for c in cands if ok(c) and any(len(a) >= 6 and len(b) >= 6 and (a in b or b in a) and min(len(a),len(b))/max(len(a),len(b)) >= 0.7 for a in c['keys'] for b in k)]
    if not m and re.search(r'weir|barrage', dam, re.I):
        k2 = {x.replace('weir','').replace('barrage','') for x in k}
        m = [c for c in cands if ok(c) and re.search(r'weir|barrage', c['name'], re.I) and {x.replace('weir','').replace('barrage','') for x in c['keys']} & k2]
    w = sorted([c for c in m if c['src']=='w'], key=lambda c: (-(('dam' in c['name'].lower()) or c['tags'].get('water')=='reservoir' or c['tags'].get('landuse')=='reservoir'), -float(c['km2'])))
    if w: w = [w[0]] + [x for x in w[1:] if dist((float(x['lon']),float(x['lat'])),(float(w[0]['lon']),float(w[0]['lat']))) <= 5]
    d = [c for c in m if c['src']=='d']
    out.append({'station': st, 'dam': dam, 'river': river, 'provinces': provs, 'capacity': cap,
      'water': [(c['fid'], c['osm'], c['name'], round(float(c['km2']),3), float(c['lon']), float(c['lat']), ' '.join(sorted(c['provs']))) for c in w],
      'walls': [(c['fid'], c['osm'], c['name'], float(c['lon']), float(c['lat']), ' '.join(sorted(c['provs']))) for c in d]})
json.dump(out, open(f'{S}/match1.json','w'), indent=0)
nw = sum(1 for o in out if o['water']); nd = sum(1 for o in out if not o['water'] and o['walls']); 
print('water name match', nw, 'wall only', nd, 'none', sum(1 for o in out if not o['water'] and not o['walls']))
multi = [o for o in out if len(o['water'])>1]
print('multi water', len(multi))
for o in multi[:40]:
    big = o['water'][0]
    far = [x for x in o['water'][1:] if dist((x[4],x[5]),(big[4],big[5])) > 5]
    if far: print(o['station'], o['dam'], [(x[2], x[3], x[6], round(dist((x[4],x[5]),(big[4],big[5])))) for x in o['water'][:5]])
print('NONE:', [(o['station'], o['dam'], o['provinces']) for o in out if not o['water'] and not o['walls']])
