#!/usr/bin/env python3
##########################################################################
# codePost submission CLI
#
# DATE:    2019-02-12
# AUTHOR:  codePost (team@codepost.io)
# PARAMETERS:
# api_key
# course_name
# course_term
# assignment_name
# students (list of emails)
# files (list of filenames)
#
##########################################################################

import os
import sys
from yaml import load, dump
from argparse import ArgumentParser, FileType
import codePost_upload_utils as cpUpload


class color:
    PURPLE = '\033[95m'
    CYAN = '\033[96m'
    DARKCYAN = '\033[36m'
    BLUE = '\033[94m'
    GREEN = '\033[92m'
    YELLOW = '\033[93m'
    RED = '\033[91m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'
    END = '\033[0m'


_TERM_ERROR = (color.END + color.RED + "[" + color.BOLD +
               "ERROR" +
               color.END + color.RED + "]" + color.END)

_TERM_WARN = (color.END + color.BLUE + "[" + color.BOLD +
              "WARNING" +
              color.END + color.BLUE + "]" + color.END)

_TERM_OK = (color.END + color.GREEN + "[" + color.BOLD +
            "OK" +
            color.END + color.GREEN + "]" + color.END)

_TERM_INFO = (color.END + "[" + color.BOLD +
              "INFO" +
              color.END + "]" + color.END)

try:
    import click

except ImportError:
    print(_TERM_ERROR + " This tool requires the 'click' python package.", file=sys.stderr)
    print("Try installing the package locally:", file=sys.stderr)
    print("    pip install --user click", file=sys.stderr)
    sys.exit(99)


def _print_err(msg, fatal=None):
    click.echo(message=_TERM_ERROR + " " + msg, err=True)
    # fatal contains an error number; if non-empty, exit
    if fatal != None:
        sys.exit(fatal)


def _print_warn(msg):
    click.echo(message=_TERM_WARN + " " + msg, err=True)


def _print_info(msg):
    click.echo(message=_TERM_INFO + " " + msg, err=True)


def _print_ok(msg):
    click.echo(message=_TERM_OK + " " + msg, err=False)


try:
    from yaml import CLoader as Loader, CDumper as Dumper
except ImportError:
    from yaml import Loader, Dumper

##########################################################################

# Try to load command line parameters
parser = ArgumentParser()
parser.add_argument('-api_key', help='The API key to authenticate upload')
parser.add_argument(
    '-course_name', help='The name of the course to upload to (e.g. COS126)')
parser.add_argument(
    '-course_period', help='The period of the course to upload to (e.g. S2019)')
parser.add_argument('-assignment_name',
                    help='The name of the assignment to upload to (e.g. Loops)')
parser.add_argument('-students', help='Comma-separated list of student emails')
parser.add_argument('-files', help='Comma-separated list of file paths',
                    nargs='+')
parser.add_argument('--extend', action='store_true',
                    help='If submission already exists, add new files to it and replace old files if the code has changed.')
parser.add_argument('--overwrite', action='store_true',
                    help='If submission already exists, overwrite it.')
args, unknown = parser.parse_known_args()

# Decide if we need to look for YAML config file. We only need to do this if an argument isn't
# specified on the command line
params = vars(args)
print(params)

needToLoadYAML = False
requiredArgs = ['api_key', 'course_name', 'course_period',
                'assignment_name', 'students', 'files']
for key in requiredArgs:
    if params[key] is None:
        needToLoadYAML = True
        break

# Load parameters from YAML file, if we need them
haveAllArgs = True
if needToLoadYAML:
    print('')
    print('*******************************************************')
    print('Configuration')
    print('*******************************************************')
    _print_info('Some arguments missing...looking for codepost-config.yaml')
    try:
        config = load(open('codepost-config.yaml'), Loader=Loader)
        for key in requiredArgs:
            if params[key] is None:
                if key in config.keys():
                    params[key] = config[key]
                    _print_info(
                        'Setting argument: %s from codepost-config' % (key))
                else:
                    _print_err(
                        'Missing argument: %s. Not specified in codepost-config or on the CLI' % (key))
                    haveAllArgs = False

    except IOError:
        _print_warn(
            'Could not find codepost-config.yaml. Please create one or specify all required arguments from the command line.')
        _print_warn(
            'To see all required arguments, run python upload-to-codePost -h')
        haveAllArgs = False

if not haveAllArgs:
    _print_err("Missing some necessary arguments, so aborting.", fatal=10)

print('')
print('*******************************************************')
print('Upload')
print('*******************************************************')

# Separate student list into actual list
studentList = params['students'].split(',')

# Iterate over file list to prepare payload for codePost-upload-utils
#fileNames = params['files'].split(',')
fileNames = params['files']
parsedFiles = []
for fileName in fileNames:
    try:
        code = open(fileName, 'r').read()
        path, extension = os.path.splitext(fileName)
        name = os.path.basename(fileName)

        # Princeton hack
        if ".output.txt" in name:
            name = "TESTS.txt"

        parsedFiles.append(
            {
                'name': name,
                'extension': extension,
                'code': code
            }
        )
    except IOError:
        _print_err("Error reading specified file: %s" % (fileName), fatal=True)


# Set upload mode
modeToUse = 0  # default to cautious mode
if params['overwrite']:
    modeToUse = 3
elif params['extend']:
    modeToUse = 2

# call upload_single_submission
try:
    cpUpload.upload_single_submission(api_key=params['api_key'],
                                      course_name=params['course_name'],
                                      course_period=params['course_period'],
                                      assignment_name=params['assignment_name'],
                                      students=studentList,
                                      files=parsedFiles,
                                      mode=modeToUse)
    _print_ok("Submission successfully uploaded.")
except RuntimeError as e:
    _print_err(str(e))

print('')
