<commit_before>"""Answer search requests, oh boy."""
# Local
import re

# Third Party
from commonregex import CommonRegex
import pandas as pd
from pyiem.templates.iem import TEMPLATE
from pyiem.util import get_sqlalchemy_conn, get_properties
from paste.request import parse_formvars
import requests

AFOS_RE = re.compile(r"^[A-Z]{5}[A-Z0-9]$", re.I)
STATION_RE = re.compile(r"^[A-Z0-9]{3,10}$", re.I)
AUTOPLOT_RE = re.compile(r"^(autoplot|ap)?\s?(?P<n>\d{1,3})$", re.I)


def station_df_handler(df):
    """Common."""
    if df.empty:
        return "/sites/locate.php"
    # Prioritize network values that contain ASOS
    df2 = df[df["network"].str.contains("ASOS")]
    if not df2.empty:
        r1 = df2.iloc[0]
    else:  # roullete
        r1 = df.iloc[0]
    return f"/sites/site.php?station={r1['id']}&network={r1['network']}"


def geocoder(q):
    """Attempt geocoding."""
    props = get_properties()
    req = requests.get(
        "https://maps.googleapis.com/maps/api/geocode/json",
        params=dict(address=q, key=props["google.maps.key2"], sensor="true"),
        timeout=30,
    )
    data = req.json()
    if not data["results"]:
        return "/sites/locate.php"
    lat = data["results"][0]["geometry"]["location"]["lat"]
    lon = data["results"][0]["geometry"]["location"]["lng"]
    with get_sqlalchemy_conn("mesosite") as conn:
        df = pd.read_sql(
            "SELECT id, network, "
            "ST_Distance(geom, "
            "ST_GeomFromEWKT('SRID=4326;POINT(%s %s)')) as dist "
            "from stations where ST_PointInsideCircle(geom, %s, %s, 1) "
            "ORDER by dist ASC LIMIT 50",
            conn,
            params=(lon, lat, lon, lat),
        )
    return station_df_handler(df)


def ap_handler(apid):
    """Forward to the appropriate autoplot page."""
    return f"/plotting/auto/?q={apid}"


def afos_handler(pil):
    """Forward to AFOS handler."""
    return f"/wx/afos/p.php?pil={pil}"


def station_handler(sid):
    """Attempt to find a station."""
    # convert KXXX to XXX
    if sid.startswith("K") and len(sid) == 4:
        sid = sid[1:]
    with get_sqlalchemy_conn("mesosite") as conn:
        df = pd.read_sql(
            "SELECT id, network from stations where id = %s",
            conn,
            params=(sid,),
        )
    return station_df_handler(df)


def find_handler(q):
    """Do we have a handler for this request?"""
    if q == "":
        return None, None
    # Match autoplot first as ### will match STATION_RE
    m = AUTOPLOT_RE.match(q)
    if m:
        d = m.groupdict()
        return ap_handler, d["n"]
    if AFOS_RE.match(q):
        return afos_handler, q.upper()
    if STATION_RE.match(q):
        return station_handler, q.upper()
    # Likely want to always do this one last, as it will catch things
    c = CommonRegex(q)
    # pylint: disable=no-member
    if c.street_addresses:
        return geocoder, q
    return None, None


def default_form():
    """Page when we don't know what to do."""
    ctx = {}
    ctx[
        "content"
    ] = """
<h3>IEM Awesome Search Failure</h3>

<p>Sorry, I don't know how to handle your request. Here's a brief listing
of supported search values.</p>

<ul>
    <li>A NWS AFOS/AWIPS Idenitifer (AFDDMX, SWODY1)</li>
    <li>A station ID (KFWS, AMSI4, DSM, IA0200)</li>
    <li>An autoplot identifier (ap1, ap2, autoplot 100)</li>
    <li>The nearest station to a street address (123 Main St Ames Iowa)</li>
</ul>
<commit_msg>hack around conflict afos/station search regex<commit_after>"""Answer search requests, oh boy."""
# Local
import re

# Third Party
from commonregex import CommonRegex
import pandas as pd
from pyiem.templates.iem import TEMPLATE
from pyiem.util import get_sqlalchemy_conn, get_properties
from paste.request import parse_formvars
import requests

AFOS_RE = re.compile(r"^[A-Z]{5}[A-Z0-9]$", re.I)
STATION_RE = re.compile(r"^[A-Z0-9]{3,10}$", re.I)
AUTOPLOT_RE = re.compile(r"^(autoplot|ap)?\s?(?P<n>\d{1,3})$", re.I)


def station_df_handler(df):
    """Common."""
    if df.empty:
        return "/sites/locate.php"
    # Prioritize network values that contain ASOS
    df2 = df[df["network"].str.contains("ASOS")]
    if not df2.empty:
        r1 = df2.iloc[0]
    else:  # roullete
        r1 = df.iloc[0]
    return f"/sites/site.php?station={r1['id']}&network={r1['network']}"


def geocoder(q):
    """Attempt geocoding."""
    props = get_properties()
    req = requests.get(
        "https://maps.googleapis.com/maps/api/geocode/json",
        params=dict(address=q, key=props["google.maps.key2"], sensor="true"),
        timeout=30,
    )
    data = req.json()
    if not data["results"]:
        return "/sites/locate.php"
    lat = data["results"][0]["geometry"]["location"]["lat"]
    lon = data["results"][0]["geometry"]["location"]["lng"]
    with get_sqlalchemy_conn("mesosite") as conn:
        df = pd.read_sql(
            "SELECT id, network, "
            "ST_Distance(geom, "
            "ST_GeomFromEWKT('SRID=4326;POINT(%s %s)')) as dist "
            "from stations where ST_PointInsideCircle(geom, %s, %s, 1) "
            "ORDER by dist ASC LIMIT 50",
            conn,
            params=(lon, lat, lon, lat),
        )
    return station_df_handler(df)


def ap_handler(apid):
    """Forward to the appropriate autoplot page."""
    return f"/plotting/auto/?q={apid}"


def afos_handler(pil):
    """Forward to AFOS handler."""
    return f"/wx/afos/p.php?pil={pil}"


def station_handler(sid):
    """Attempt to find a station."""
    # convert KXXX to XXX
    if sid.startswith("K") and len(sid) == 4:
        sid = sid[1:]
    with get_sqlalchemy_conn("mesosite") as conn:
        df = pd.read_sql(
            "SELECT id, network from stations where id = %s",
            conn,
            params=(sid,),
        )
    return station_df_handler(df)


def has_station(sid):
    """Le Sigh."""
    # convert KXXX to XXX
    if sid.startswith("K") and len(sid) == 4:
        sid = sid[1:]
    with get_sqlalchemy_conn("mesosite") as conn:
        df = pd.read_sql(
            "SELECT id, network from stations where id = %s",
            conn,
            params=(sid,),
        )
    return not df.empty


def find_handler(q):
    """Do we have a handler for this request?"""
    if q == "":
        return None, None
    # Match autoplot first as ### will match STATION_RE
    m = AUTOPLOT_RE.match(q)
    if m:
        d = m.groupdict()
        return ap_handler, d["n"]
    # Can overlap with AFOS_RE
    if STATION_RE.match(q):
        if has_station(q):
            return station_handler, q.upper()
    if AFOS_RE.match(q):
        return afos_handler, q.upper()
    # Likely want to always do this one last, as it will catch things
    c = CommonRegex(q)
    # pylint: disable=no-member
    if c.street_addresses:
        return geocoder, q
    return None, None


def default_form():
    """Page when we don't know what to do."""
    ctx = {}
    ctx[
        "content"
    ] = """
<h3>IEM Awesome Search Failure</h3>

<p>Sorry, I don't know how to handle your request. Here's a brief listing
of supported search values.</p>

<ul>
    <li>A NWS AFOS/AWIPS Idenitifer (AFDDMX, SWODY1)</li>
    <li>A station ID (KFWS, AMSI4, DSM, IA0200)</li>
    <li>An autoplot identifier (ap1, ap2, autoplot 100)</li>
    <li>The nearest station to a street address (123 Main St Ames Iowa)</li>
</ul>

{'fraction_non_alphanumeric': 0.1481681762876842, 'fraction_numerical': 0.0135189941868325, 'mean_word_length': 2.743927125506073, 'pattern_counts': {'":': 2, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '299880', 'n_tokens_mistral': 2659, 'n_tokens_neox': 2558, 'n_words': 673}