#!/usr/bin/env python

import argparse
import http.client
import json
from pathlib import Path
import ssl
import sys
import subprocess

URL="cs350.rcs.uwaterloo.ca"
SRCTAR="castoros-latest.tar.gz"

# ATTENTION: Replace these variables with the lines provided
# in the email titled "CS350 Submission Magic" to submit.
# This script can still download and create the patch solution
# even without filling in your student number and magic code.
STUDENT = None
MAGIC = None

PATCH = Path.cwd() / "castoros.patch"
ASST = None
SRCROOT = "castoros"

# No need to verify certificate
CONTEXT = ssl.create_default_context()
CONTEXT.check_hostname = False
CONTEXT.verify_mode = ssl.CERT_NONE

def check_creds_or_exit():
    if STUDENT is None:
        print("ERROR: No student ID provided")
        sys.exit(0)

    if args.magic is None:
        print("ERROR: No magic hex key provided")
        sys.exit(0)

def ping(args):
    conn = http.client.HTTPSConnection(URL, context=CONTEXT)
    conn.request("GET", "/ping")
    response = conn.getresponse()
    print(response.read().decode("utf-8"))

def download(args):
    conn = http.client.HTTPSConnection(URL, context=CONTEXT)
    conn.request("GET", "/sources/{}".format(SRCTAR))
    response = conn.getresponse()
    tarpath = Path.cwd() / SRCTAR
    with open(tarpath, "wb") as f:
        f.write(response.read())
    print("Source tarball received: {}".format(tarpath))

def submit(args):
    check_creds_or_exit()

    conn = http.client.HTTPSConnection(URL, context=CONTEXT)

    patch = ""
    with open(args.patch, "r") as f:
        patch = f.read()

    body = json.dumps({
        "patch" : patch,
        "magic" : args.magic,
    })
        
    # Create a JSON object that holds the patch
    conn.request("POST", "/submit/{}/{}".format(STUDENT, args.asst), body)
    response = conn.getresponse()
    print(response.read().decode("utf-8"))

def request_with_key(command, args):
    check_creds_or_exit()

    conn = http.client.HTTPSConnection(URL, context=CONTEXT)

    body = json.dumps({
        "magic" : args.magic,
    })
        
    conn.request("GET", "/{}/{}/{}".format(command, STUDENT, args.asst), body)
    response = conn.getresponse()
    print(response.read().decode("utf-8"))

def status(args):
    request_with_key("status", args)

def query(args):
    request_with_key("query", args)

def patch(args):
    src = str(Path.cwd() / args.srcroot)

    sp = subprocess.run(
        ["git", "-C", src, "rev-list", "--max-parents=0", "HEAD"],
        stdout=subprocess.PIPE)

    firsthash = sp.stdout.decode("utf-8").strip()

    with open(args.patch, "w") as f:
        subprocess.run(
            ["git", "-C", src, "diff", firsthash, "HEAD"],
            stdout=f)

commands = {
        "ping" : ping,
        "download" : download,
        "query" : query,
        "submit" : submit,
        "status" : status,
        "patch" : patch,
}

def get_parser():
    parser = argparse.ArgumentParser(
            prog="CS350 Client",
            description="Client for the CS350 submission server")
    parser.add_argument("command", choices=list(commands.keys()))
    parser.add_argument("-m", "--magic", default=MAGIC)
    parser.add_argument("-a", "--asst", default=ASST)
    parser.add_argument("-s", "--srcroot", default=SRCROOT)
    parser.add_argument("-p", "--patch", default=PATCH)

    return parser

if __name__ == "__main__":
    parser = get_parser()
    args = parser.parse_args()
    if args.command in ["query", "status", "submit"] and args.asst is None:
        print("ERROR: Please provide an assignment number with -a")
        sys.exit(0)

    commands[args.command](args)
