from typing import Dict
import collections


def parse_packer_log(packer_log: str) -> Dict[str, str]:
    """Parse the output of packer's -machine-readable format, strange though it may be."""
    out = {}

    lines = packer_log.strip().split("\n")
    fields = [line.split(",") for line in lines]
    # We only care about artifact lines with exactly six fields.
    ArtifactLine = collections.namedtuple(
        "ArtifactLine", "time builder linetype index msgtype val"
    )

    # We only care about artifact lines with exactly 6 fields.
    artifact_lines = [
        ArtifactLine(*f) for f in fields if len(f) == 6 and f[2] == "artifact"
    ]

    # Get the ami images, which should match lines like this one (line break for readability):
    #   1598642161,amazon-ebs,artifact,0,id,us-east-1:
    #       ami-04894a7352df9fdf9%!(PACKER_COMMA)us-west-2:ami-017627938fe327e4f
    ami_lines = [
        a
        for a in artifact_lines
        if a.builder.startswith("amazon-ebs") and a.msgtype == "id" and a.val
    ]
    assert (
        len(ami_lines) == 2
    ), f"expected two matching ami ids line but got: {ami_lines}"

    for ami_line in ami_lines:
        ami_fields = ami_line.val.split("%!(PACKER_COMMA)")
        for ami_field in ami_fields:
            region, ami = ami_field.split(":")
            name = region.replace("-", "_") + "_agent_ami"
            out[name] = ami

    # Get the GCP builder name by matching the build-id from a line like this one:
    #   1598642161,det-environments-06318c7,artifact,0,builder-id,packer.googlecompute
    gcp_builders = [
        a.builder
        for a in artifact_lines
        if a.msgtype == "builder-id" and a.val == "packer.googlecompute"
    ]
    # aws gov images do not have matching gcp environment images.
    if len(gcp_builders) == 0:
        return out
    assert len(gcp_builders) == 1, f"expected one gcp builder but got: {gcp_builders}"
    gcp_builder = gcp_builders[0]

    # Get the GCP artifact ID by matching a line like this one:
    #    1598642161,det-environments-06318c7,artifact,0,id,det-environments-06318c7
    gcp_ids = [
        a.val
        for a in artifact_lines
        if a.builder == gcp_builder and a.msgtype == "id" and a.val
    ]
    assert len(gcp_ids) == 1, f"expected one matching gcp id line but got: {gcp_ids}"
    out["gcp_env"] = gcp_ids[0]

    return out