#!/usr/bin/env python3

import codecs
import json
import sys
import textwrap
import urllib.request

sys.stdin = codecs.getreader("utf-8")(sys.stdin.detach())
sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach())

entries = []


def add_entry(entry):
    global tracking_bug

    if entry and "ignore" not in entry:
        combo = []
        for bug in set(entry.get("bugs", [])):
            combo.append(bug)
        for cve in set(entry.get("cves", [])):
            combo.append(cve)
        combo = sorted(combo)

        if len(combo) == 0:
            if entry.get("subject", "").startswith("UBUNTU"):
                combo = "__packaging__"
            else:
                combo = "__mainline__"
        else:
            if entry.get("subject", "") == "UBUNTU: link-to-tracker: update tracking bug":
                tracking_bug = combo
            if combo not in keys:
                keys.append(combo)

        entry["key"] = combo
        entries.append(entry)


# Suck up the git log output and extract the information we need.
keys = []
tracking_bug = None
entry = None
subject_wait = False
for line in sys.stdin:
    if line.startswith("commit "):
        add_entry(entry)
        entry = {}
        subject_wait = True

    elif line.startswith("Author: "):
        bits = line.strip().split(maxsplit=1)
        entry["author"] = bits[1]

    elif subject_wait and line.startswith("    "):
        subject_wait = False
        entry["subject"] = line.strip()

    elif line.startswith("    BugLink: "):
        bits = line.strip().split(maxsplit=2)
        if len(bits) > 2:
            # There is text after the URL, so use that (after stripping the
            # enclosing characters)
            entry.setdefault("bugs", []).append(bits[2][1:-1])
        elif "launchpad.net" in bits[1]:
            # Extract the bug number from the launchpad URL
            bits = bits[1].split("/")
            entry.setdefault("bugs", []).append(bits[-1])

    elif line.startswith("    CVE-"):
        entry.setdefault("cves", []).append(line.strip())

    elif line.startswith("    Ignore:"):
        entry["ignore"] = True

    elif line.startswith("    Properties:"):
        for prop in line.strip().split()[1:]:
            if prop in ("ignore", "no-changelog"):
                entry["ignore"] = True

add_entry(entry)

entries.reverse()

# Go through the entries and clear out authors for upstream commits.
for entry in entries:
    if entry["subject"].startswith("UBUNTU:"):
        entry["subject"] = entry["subject"][7:].strip()
    else:
        del entry["author"]

# Lump everything without a bug at the bottom.
keys.append("__packaging__")
keys.append("__mainline__")

# Ensure we list the tracking bug updates first.
if tracking_bug is not None:
    keys.remove(tracking_bug)
    keys.insert(0, tracking_bug)

emit_nl = False
for key in keys:
    if key == "__packaging__":
        title_set = ["Miscellaneous Ubuntu changes"]
    elif key == "__mainline__":
        title_set = ["Miscellaneous upstream changes"]
    else:
        title_set = []
        for bug in key:
            if bug.startswith("CVE-"):
                title_set.append(bug)
            elif bug.isdigit():
                # Assume that it is an LP bug number if 'bug' contains only digits
                bug_info = None

                try:
                    # urllib.request.urlcleanup()
                    request = urllib.request.Request("https://api.launchpad.net/devel/bugs/" + bug)
                    request.add_header("Cache-Control", "no-cache")
                    with urllib.request.urlopen(request) as response:
                        data = response.read()
                        bug_info = json.loads(data.decode("utf-8"))

                    title = bug_info["title"]
                    if "description" in bug_info:
                        for line in bug_info["description"].split("\n"):
                            if line.startswith("Kernel-Description:"):
                                title = line.split(" ", 1)[1]

                except urllib.error.HTTPError:
                    title = "INVALID or PRIVATE BUG"

                title += " (LP###" + bug + ")"
                title_set.append(title)
            else:
                # Finally treat 'bug' itself as the title
                title_set.append(bug)

    emit_title = True
    for entry in entries:
        if entry["key"] != key:
            continue

        if emit_title:
            if emit_nl:
                print("")
            emit_nl = True

            title_lines = textwrap.wrap("#// ".join(title_set), 76)
            print("  * " + title_lines[0].replace("LP###", "LP: #").replace("#//", " //"))
            for line in title_lines[1:]:
                line = line.replace("LP###", "LP: #").replace("#//", " //")
                print("    " + line)

            emit_title = False

        if key != tracking_bug or (key == tracking_bug and entry["subject"] != "link-to-tracker: update tracking bug"):
            title_lines = textwrap.wrap(entry["subject"], 76)
            print("    - " + title_lines[0])
            for line in title_lines[1:]:
                line = line.replace("LP###", "LP: #")
                print("      " + line)
