#!/usr/bin/env python3

import json
import os
import platform
import shutil
import subprocess


def is_local():
    """Check whether the file is running locally or on Gradescope"""
    return False if os.getcwd().startswith("/autograder") else True


def init():
    """Initialize the environment before compilation can be done."""
    if is_local():
        init_local()
    else:
        init_server()


def init_local():
    """Copy files into the appropriate local directories."""
    copy_files(".")


def init_server():
    """Copy files into the appropriate Gradescope server directories."""
    copy_files("source")
    copy_req_files(["MyString.java"], "source/tmp")
    os.chdir("source")


def copy_files(dir):
    """Helper method for copying files into local/server directories."""
    shutil.rmtree(f"{dir}/tmp", ignore_errors=True)
    os.mkdir(f"{dir}/tmp")
    shutil.copytree(f"{dir}/src/main/java", f"{dir}/tmp/java")


def copy_req_files(files, dir):
    """Copy student-provided files into the appropriate directory.

    :raise Exception: if a required file is not found

    """
    for file in files:
        path = f"/autograder/submission/{file}"
        if os.path.exists(path):
            shutil.copy(path, f"{dir}/java")
        else:
            raise Exception(f"File {file} not found.")


def compile():
    """Compile the project.

    This must be done after calling init() and before calling run().

    :raise Exception: if there is a compilation error.
    """
    os.chdir("tmp")
    result = subprocess.run(
        "javac -g -encoding UTF8 -Xlint:none -d classes java/MyString.java java/HashExercise.java java/HashSet.java",
        shell=True,
        stderr=subprocess.PIPE)
    if result.returncode != 0:
        raise Exception("Compilation error: " + result.stderr.decode("UTF-8"))
    os.chdir("..")


def run():
    """Run the compiled project, outputting the results.

    Results are written to stdout if run locally, to a file if run on the server.

    :raise Exception: if the result of the run is not 0.
    """
    os.chdir("tmp/classes")
    sep = ';' if platform.system() == "Windows" else ":"
    result = subprocess.run(
        f"java -cp .{sep}../../src/main/resources HashExercise",
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE)
    if result.returncode != 0:
        raise Exception("Runtime error: " + result.stderr.decode("UTF-8"))
    output(result.stdout.decode())


def output(s):
    """Output to stdout if run locally or a file if run on the Gradescope server. """
    if is_local():
        print(s)
    else:
        with open("/autograder/results/results.json", "w") as text_file:
            text_file.write(s)


def output_error(e):
    """Output an error."""
    data = {"score": 0, "output": str(e)}
    output(json.dumps(data))


def main():
    try:
        init()
        compile()
        run()
    except Exception as e:
        output_error(e)

if __name__ == "__main__":
    main()
