#!/usr/bin/env python

import argparse
from subprocess import call, STDOUT
import sys
import os.path
import os

VERSION = "0.1"
main_dir = os.path.dirname(os.path.realpath(__file__)) + "/"
fnull = open(os.devnull, 'w')

parser = argparse.ArgumentParser(
    prog = "Crab",
    description="Launch tool for Crab, a small functional Programming language")


parser.add_argument('filenames',
                    metavar='filename',
                    nargs="+",
                    help="Run Crab program specified"
                    )

parser.add_argument('--output', '-o',
                    action='store',
                    help="Output executable or object file for Crab"
                   )
parser.add_argument('--compile', '-c',
                    action='store_true',
                    help="Compile file to an object file")

parser.add_argument('--version', action='version', version='%(prog)s {}'.format(VERSION))

args = parser.parse_args()


def call_exit(arr):
    ret = call(arr)
    if ret == 0:
        return
    else:
        print("Program exited with return value {}".format(ret))
        sys.exit(1)

def compile(files, output="a"):
    try:
        call_exit(["gcc", "-o", output] + files + [main_dir + "prelude.o"])
    except OSError as e:
        if e.errno == os.errno.ENOENT:
            print("""Currently, Crab only supports linking with GCC. 
                    If you want to use a different linker, you will need to pass the -c option to Crab """)


if len(sys.argv) == 1:
    parser.print_help()
    sys.exit(1)

if len(args.filenames) > 0:
    fnames = args.filenames
    for filename in fnames:
        if os.path.isfile(filename):
            # If this doesn't exist, the user hasn't built yet, or it's not in the path
            try:
                call_exit(["crab_compiler", filename])
            except FileNotFoundError:
                try:
                    call_exit(["./crab_compiler", filename])
                except FileNotFoundError: 
                    print("Please build before running, or add Crab to your PATH variable.")
                    sys.exit(0)
        else:
            print("Argument " + filename + " is not a file.")
            sys.exit(1)

# Create an executable
if args.output is not None:
    output = args.output
else:
    output = "a.out"

filenames = []
for fname in args.filenames:
    directory = os.path.dirname(fname)
    filename = os.path.basename(fname)
    name = filename.split(".")[-2]
    name += ".o"
    filenames.append(directory + name)

if args.compile:
    # We want to compile multiple .o files into one .o file
    call_exit(["ld", "-r"] + filenames + [main_dir + 'prelude.o', "-o", output])
    # Quietly delete all .o files
    for fname in filenames:
        call(["rm", fname], stdout=fnull, stderr=STDOUT)
else:
    # We want to convert a source file into an executable
    compile(filenames, output)
    # Same thing as above 
    for fname in filenames:
        call(["rm", fname], stdout=fnull, stderr=STDOUT)
