from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw

import requests
from twc_icon_codes import engFcst


def draw_text_psd_style(draw, xy, text, font, tracking=0, leading=None, **kwargs):
    """
    usage: draw_text_psd_style(draw, (0, 0), "Test",
                tracking=-0.1, leading=32, fill="Blue")

    Leading is measured from the baseline of one line of text to the
    baseline of the line above it. Baseline is the invisible line on which most
    letters—that is, those without descenders—sit. The default auto-leading
    option sets the leading at 120% of the type size (for example, 12-point
    leading for 10-point type).

    Tracking is measured in 1/1000 em, a unit of measure that is relative to
    the current type size. In a 6 point font, 1 em equals 6 points;
    in a 10 point font, 1 em equals 10 points. Tracking
    is strictly proportional to the current type size.
    """

    def stutter_chunk(lst, size, overlap=0, default=None):
        for i in range(0, len(lst), size - overlap):
            r = list(lst[i : i + size])
            while len(r) < size:
                r.append(default)
            yield r

    x, y = xy
    font_size = font.size
    lines = text.splitlines()
    if leading is None:
        leading = font.size * 1.2
    for line in lines:
        for a, b in stutter_chunk(line, 2, 1, " "):
            w = font.getlength(a + b) - font.getlength(b)
            # dprint("[debug] kwargs")
            # print("[debug] kwargs:{}".format(kwargs))

            draw.text((x, y), a, font=font, **kwargs)
            x += w + (tracking / 1000) * font_size
        y += leading
        x = xy[0]


def draw_text_psd_style_shadow(draw, xy, text, font, tracking=0, leading=None, shadowcolor=(0,0,0), shadowwidth=1, shadowheight=1, **kwargs):
    kwargs_no_fill = kwargs.copy()
    if 'fill' in kwargs_no_fill:
        del kwargs_no_fill['fill']

    x, y = xy

    draw_text_psd_style(draw, (x+shadowwidth, y), text, font, tracking, leading, fill=shadowcolor, **kwargs_no_fill)
    draw_text_psd_style(draw, (x, y+shadowheight), text, font, tracking, leading, fill=shadowcolor, **kwargs_no_fill)
    draw_text_psd_style(draw, (x+shadowwidth, y+shadowheight), text, font, tracking, leading, fill=shadowcolor, **kwargs_no_fill)

    draw_text_psd_style(draw, xy, text, font, tracking, leading, **kwargs)


def draw_shadow(draw, x, y, text, font, fill, shadowcolor, shadowwidth=1, shadowheight=1):
    # thin border
    draw.text((x + shadowwidth, y), text, font=font, fill=shadowcolor)
    # draw.text((x+1, y), text, font=font, fill=shadowcolor)
    draw.text((x, y + shadowheight), text, font=font, fill=shadowcolor)
    # draw.text((x, y+1), text, font=font, fill=shadowcolor)
    draw.text((x + shadowwidth, y + shadowheight), text, font=font, fill=shadowcolor)

    # # thicker border
    # draw.text((x-1, y-1), text, font=font, fill=shadowcolor)
    # draw.text((x+1, y-1), text, font=font, fill=shadowcolor)
    # draw.text((x-1, y+1), text, font=font, fill=shadowcolor)
    # draw.text((x+1, y+1), text, font=font, fill=shadowcolor)

    draw.text((x, y), text, font=font, fill=fill)

    return draw


def generate_hourly_slide(slide_order, slide_data, hourly_slide_header):
    print(f"Creating Hourly Slide #{slide_order}")

    # Load data/static/forecast_completely_blank.png
    output_image = Image.open("data/static/slides/forecast_completely_blank.png")

    # Add the header text to the top
    # TODO: YOINK
    font = ImageFont.truetype("data/static/slides/Interstate-Regular.ttf", 26)
    draw = ImageDraw.Draw(output_image)
    # draw.text((70, 42), "TUESDAY FORECAST", (255,255,255), font=font)
    draw_text_psd_style(
        draw, (70, 42), hourly_slide_header, font, fill=(255, 255, 255), tracking=40
    )

    font_label = ImageFont.truetype("data/static/slides/Interstate-Bold.ttf", 22)
    font_time_label = ImageFont.truetype(
        "data/static/slides/Interstate-Regular.ttf", 18
    )
    font_temp = ImageFont.truetype("data/static/slides/Interstate-Bold.ttf", 24)
    for i, city in enumerate(slide_data):
        # Add the city labels
        label_pos_x = 73
        label_pos_y = 85
        if i in [1, 3]:
            label_pos_x = 344
        if i in [2, 3]:
            label_pos_y = 226
        # draw.text((label_pos_x, label_pos_y), city['city_label'], (0,0,0), font=font_label)
        draw_text_psd_style(
            draw,
            (label_pos_x, label_pos_y),
            city["city_label"],
            font_label,
            fill=(0, 0, 0),
        )

        # Add the data
        for j, data in enumerate(city["data"]):
            # Time header
            _, _, header_text_w, _ = draw.textbbox(
                (0, 0), data["header_label"], font=font_time_label
            )
            header_text_anchor_x = label_pos_x + (j * 84) - 3
            header_text_anchor_y = label_pos_y + 31
            # TEST BOX
            # draw.rectangle(((header_text_anchor_x, header_text_anchor_y), (header_text_anchor_x+72, header_text_anchor_y+10)), outline="red")
            # draw.text(
            #     (
            #         header_text_anchor_x+((72-header_text_w)/2),
            #         header_text_anchor_y
            #     ),
            #     data['header_label'],
            #     font=font_time_label,
            #     fill=(255, 255, 255)
            # )
            if data["header_label"] == "Midnight":
                header_text_anchor_x -= 2
            draw_text_psd_style(
                draw,
                (
                    header_text_anchor_x + ((72 - header_text_w) / 2),
                    header_text_anchor_y,
                ),
                data["header_label"],
                font_time_label,
                fill=(255, 255, 255),
                tracking=45,
            )

            # Icon
            icon = engFcst[data["icon_code"]]

            # Open the PNG file
            icon_image = Image.open(f"data/static/slides/large/{icon.iconFile}.png")

            # Advance the frame
            # icon_image = Image.open(f"data/static/slides/map/{icon.iconFile}.png")
            # icon_image.seek(11)

            # Resize it
            icon_width = 64
            icon_height = 59
            icon_image = icon_image.resize((icon_width, icon_height))

            # Paste the icon
            icon_anchor_x = label_pos_x + (j * 84) + 3 - 3
            icon_anchor_y = label_pos_y + 50 - 3
            # output_image.paste(icon_image, (icon_anchor_x, icon_anchor_y), icon_image)
            output_image.alpha_composite(icon_image, (icon_anchor_x, icon_anchor_y))
            # TEST BOX
            # draw.rectangle(((icon_anchor_x, icon_anchor_y), (icon_anchor_x+icon_width, icon_anchor_y+icon_height)), outline="red")

            # Temperature
            _, _, temp_text_w, _ = draw.textbbox(
                (0, 0), data["temperature"], font=font_temp
            )
            temp_text_anchor_x = label_pos_x + (j * 84) - 5
            temp_text_anchor_y = label_pos_y + 105
            # TEST BOX
            # draw.rectangle(((temp_text_anchor_x, temp_text_anchor_y), (temp_text_anchor_x+72, temp_text_anchor_y+10)), outline="red")

            draw = draw_shadow(
                draw,
                temp_text_anchor_x + ((72 - temp_text_w) / 2),
                temp_text_anchor_y,
                data["temperature"],
                font_temp,
                # (223, 248, 178),
                # (218, 227, 145),
                (255, 251, 128),
                (0, 0, 0),
            )

    # Save the image
    output_image.save(f"temp/hourly_{slide_order}.png")


def generate_3day_slide(slide_order, slide_data):
    print(f"Creating 3-Day Slide #{slide_order}")

    # Load data/static/slides/3_day_forecast_blank.png
    output_image = Image.open("data/static/slides/3_day_forecast_blank.png").convert(
        mode="RGBA"
    )

    # Add the header text to the top
    # TODO: YOINK
    # font = ImageFont.truetype("data/static/slides/Interstate-Regular.ttf", 26)
    draw = ImageDraw.Draw(output_image)
    # draw.text((70, 42), "TUESDAY FORECAST", (255,255,255), font=font)
    # draw_text_psd_style(draw, (70, 42), "TUESDAY FORECAST", font, fill=(255,255,255), tracking=40)

    font_label = ImageFont.truetype(
        "data/static/slides/Interstate-BoldCondensed.ttf", 22
    )
    font_time_label = ImageFont.truetype("data/static/slides/Interstate-Bold.ttf", 17)
    font_temp = ImageFont.truetype(
        "data/static/slides/Interstate-BoldStretched.ttf", 24
    )
    for i, city in enumerate(slide_data):
        # Add the city labels
        label_pos_x = 71
        label_pos_y = 104
        if i in [1, 3]:
            label_pos_y = 169
        if i in [2, 3]:
            label_pos_y = 234
        if i in [3, 3]:
            label_pos_y = 299
        # draw.text((label_pos_x, label_pos_y), city['city_label'], (0,0,0), font=font_label)
        draw_text_psd_style(
            draw,
            (label_pos_x, label_pos_y),
            city["city_label"],
            font_label,
            fill=(0, 0, 0),
        )

        # TODO: render the first of the four instead of all four
        if i == 0:
            for j, data in enumerate(city["data"]):
                # Time header
                _, _, header_text_w, _ = draw.textbbox(
                    (0, 0), data["header_label"], font=font_time_label
                )
                header_text_anchor_x = label_pos_x + (j * 109) + 206
                header_text_anchor_y = label_pos_y - 27
                # TEST BOX
                # draw.rectangle(((header_text_anchor_x, header_text_anchor_y), (header_text_anchor_x+72, header_text_anchor_y+10)), outline="red")
                draw.text(
                    (
                        header_text_anchor_x + ((72 - header_text_w) / 2),
                        header_text_anchor_y,
                    ),
                    data["header_label"].upper(),
                    font=font_time_label,
                    fill=(0, 0, 0),
                    tracking=60,
                )

        # Add the data
        for j, data in enumerate(city["data"]):
            # Adds the icon a set number of times in an attempt to emulate the drop shadow
            for _ in range(2):
                # Icon
                icon = engFcst[data["icon_code"]]

                # Open the PNG file
                icon_image = Image.open(
                    f"data/static/slides/medium/{icon.iconFile}.png"
                )

                # Advance the frame
                # icon_image = Image.open(f"data/static/slides/map/{icon.iconFile}.png")
                # icon_image.seek(11)

                # Resize it
                icon_width = 54
                icon_height = 55
                icon_image = icon_image.resize((icon_width, icon_height))

                # Paste the icon
                icon_anchor_x = label_pos_x + (j * 108) + 232
                icon_anchor_y = label_pos_y
                # output_image.paste(icon_image, (icon_anchor_x, icon_anchor_y), icon_image)
                output_image.alpha_composite(icon_image, (icon_anchor_x, icon_anchor_y))
                # TEST BOX
                # draw.rectangle(((icon_anchor_x, icon_anchor_y), (icon_anchor_x+icon_width, icon_anchor_y+icon_height)), outline="red")

                # Add AM or PM if needed, based on the beginning of the icon file
                modifier_image = None
                if icon.iconFile.startswith("AM") or "AM" in icon.iconFile:
                    modifier_image = Image.open(f"data/static/slides/am_overlay.png")
                elif icon.iconFile.startswith("PM") or "PM" in icon.iconFile:
                    modifier_image = Image.open(f"data/static/slides/pm_overlay.png")

                if modifier_image:
                    modifier_image = modifier_image.resize((icon_width, icon_height))
                    output_image.alpha_composite(
                        modifier_image, (icon_anchor_x, icon_anchor_y)
                    )

            # High Temperatures
            _, _, temp_text_w, _ = draw.textbbox(
                (0, 0), data["high_temp"], font=font_temp
            )
            temp_text_anchor_x = label_pos_x + (j * 108) + 182
            temp_text_anchor_y = label_pos_y + 6
            box_width = 72 - 30
            # TEST BOX
            # draw.rectangle(((temp_text_anchor_x, temp_text_anchor_y), (temp_text_anchor_x+box_width, temp_text_anchor_y+10)), outline="red")

            draw = draw_shadow(
                draw,
                temp_text_anchor_x + ((box_width - temp_text_w)),
                temp_text_anchor_y,
                data["high_temp"],
                font_temp,
                # (223, 248, 178),
                # (218, 227, 145),
                (255, 251, 128),
                (0, 0, 0),
            )

            # Low Temperatures
            _, _, temp_text_w, _ = draw.textbbox(
                (0, 0), data["low_temp"], font=font_temp
            )
            temp_text_anchor_x = label_pos_x + (j * 108) + 182
            temp_text_anchor_y = label_pos_y + 29
            # draw.rectangle(((temp_text_anchor_x, temp_text_anchor_y), (temp_text_anchor_x+box_width, temp_text_anchor_y+10)), outline="red")

            draw = draw_shadow(
                draw,
                temp_text_anchor_x + ((box_width - temp_text_w)),
                temp_text_anchor_y,
                data["low_temp"],
                font_temp,
                # (223, 248, 178),
                # (218, 227, 145),
                (255, 251, 128),
                (0, 0, 0),
            )

    # Save the image
    output_image.save(f"temp/3day_{slide_order}.png")


def process_data_frames():
    url = "https://wxdata-us-central1.opntele.com/twc_star/satlf_data"

    res = requests.get(url)
    res.raise_for_status()
    data = res.json()

    # Hourly
    for i, slide_data in enumerate(data["hourly_data"]):
        generate_hourly_slide(i, slide_data, data["hourly_slide_header"])

    # Travel
    # TODO:

    # 3 Day
    for i, slide_data in enumerate(data["three_day_data"]):
        generate_3day_slide(i, slide_data)

    # Precip
    # TODO:

    # T-storm
    # TODO:

    # Radsat
    # In other file

    # Warnings
    # TODO:

    print("Done processing data frames")

    return "ok"


if __name__ == "__main__":
    process_data_frames()
