"""Frontend for Feature Content, such that we can make some magic happen"""

import os
import pathlib
import re
from datetime import date
from io import BytesIO

from matplotlib.figure import Figure
from pyiem.database import get_sqlalchemy_conn, sql_helper
from pyiem.exceptions import IncompleteWebRequest
from pyiem.webutil import iemapp
from sqlalchemy.engine import Connection

PATTERN = re.compile(
    r"^/onsite/features/(?P<yyyy>[0-9]{4})/(?P<mm>[0-9]{2})/"
    r"(?P<yymmdd>[0-9]{6})(?P<extra>.*)\."
    r"(?P<suffix>png|gif|jpg|xls|pdf|gnumeric|mp4)$"
)


def dblog(conn: Connection, yymmdd: str):
    """Log this request"""
    dt = date(2000 + int(yymmdd[:2]), int(yymmdd[2:4]), int(yymmdd[4:6]))
    conn.execute(
        sql_helper(
            "UPDATE feature SET views = views + 1 WHERE date(valid) = :dt"
        ),
        {"dt": dt},
    )
    conn.commit()


def get_content_type(val):
    """return the content-type header entry."""
    if val == "text":
        ct = "text/plain"
    elif val in ["png", "gif", "jpg"]:
        ct = f"image/{val}"
    elif val == "mp4":
        ct = f"video/{val}"
    elif val == "pdf":
        ct = f"application/{val}"
    else:
        ct = "text/plain"
    return ("Content-type", ct)


@iemapp()
def application(environ: dict, start_response: callable):
    """Process this request

    This should look something like "/onsite/features/2016/11/161125.png"
    """
    headers = [("Accept-Ranges", "bytes")]
    uri = environ.get("REQUEST_URI")
    # Option 1, no URI is provided.
    if uri is None:
        raise IncompleteWebRequest("Missing parameters in request")
    match = PATTERN.match(uri)
    # Option 2, the URI pattern is unknown.
    if match is None:
        raise IncompleteWebRequest("Missing parameters in request")

    data = match.groupdict()
    fn = (
        "/mesonet/share/features/%(yyyy)s/%(mm)s/"
        "%(yymmdd)s%(extra)s.%(suffix)s"
    ) % data
    # Option 3, we have no file.
    if not os.path.isfile(fn):
        headers.append(get_content_type("png"))
        fig = Figure()
        ax = fig.add_subplot(1, 1, 1)
        ax.text(
            0.5,
            0.5,
            "Feature Image was not Found!",
            transform=ax.transAxes,
            ha="center",
        )
        ax.axis("off")
        ram = BytesIO()
        fig.savefig(ram, format="png")
        ram.seek(0)
        start_response("404 Not Found", headers)
        return [ram.read()]

    # Option 4, we can support this request.
    headers.append(get_content_type(data["suffix"]))
    rng = environ.get("HTTP_RANGE", "bytes=0-")
    tokens = rng.replace("bytes=", "").split("-", 1)
    resdata = pathlib.Path(fn).read_bytes()
    totalsize = len(resdata)
    stripe = slice(
        int(tokens[0]),
        totalsize if tokens[-1] == "" else (int(tokens[-1]) + 1),
    )
    status = "200 OK"
    if totalsize != (stripe.stop - stripe.start):
        status = "206 Partial Content"
    headers.append(("Content-Length", "%.0f" % (stripe.stop - stripe.start,)))
    if environ.get("HTTP_RANGE") and stripe is not None:
        secondval = (
            ""
            if environ.get("HTTP_RANGE") == "bytes=0-"
            else (stripe.stop - 1)
        )
        headers.append(
            (
                "Content-Range",
                f"bytes {stripe.start}-{secondval}/{totalsize}",
            )
        )
    try:
        with get_sqlalchemy_conn("mesosite", rw=True) as conn:
            dblog(conn, data["yymmdd"])
    except Exception:
        # swallow as uninteresting
        pass
    finally:
        # Swallow exception
        start_response(status, headers)
    return [resdata[stripe]]
