'''
Python script for uploading/downloading scripts for use with the game Screeps.

http://support.screeps.com/hc/en-us/articles/203022612-Commiting-scripts-using-direct-API-access

Usage:

    #
    # general help/usage
    #

    python3 manager.py --help

    #
    # retrieve all scripts from the game and store them
    # in the folder "some_folder"
    #

    python3 manager.py from_game some_folder

    #
    # send all *.js files to the game
    #

    python3 manager.py to_game some_folder

WARNING: Use at your own risk! Make backups of all your game content!

'''

import sys
import os
import argparse
import json

import requests
from requests.auth import HTTPBasicAuth

SCREEPS_ENDPOINT = 'https://screeps.com/api/user/code'

USER_ENV = 'SCREEPS_USER'
PASSWORD_ENV = 'SCREEPS_PASSWORD'

TO_SCREEPS = 'to_game'
FROM_SCREEPS = 'from_game'


def get_user_from_env():

    user = os.environ.get('SCREEPS_USER')

    if not user:
        print('You must provide a username, i.e. export '
              '{}=<your email address>'.
              format(USER_ENV))
        sys.exit()

    return user


def get_password_from_env():

    password = os.environ.get('SCREEPS_PASSWORD')

    if not password:
        print('You must provide a password, i.e. export {}=<your password>'.
              format(PASSWORD_ENV))
        sys.exit()

    return password


def get_data(user, password):

    print('Retrieving data...')

    response = requests.get(SCREEPS_ENDPOINT,
                            auth=HTTPBasicAuth(user, password))

    response.raise_for_status()

    data = response.json()

    if data['ok'] != 1:
        raise Exception()

    return data


def send_data(user, password, modules):

    auth = HTTPBasicAuth(user, password)
    headers = {'Content-Type': 'application/json; charset=utf-8'}

    data = {'modules': modules}

    resp = requests.post(SCREEPS_ENDPOINT,
                         data=json.dumps(data),
                         headers=headers,
                         auth=auth)

    resp.raise_for_status()


def check_for_collisions(target_folder, modules):

    for module in modules:

        target = os.path.join(target_folder, '{}.js'.format(module))

        if os.path.exists(target):

            print('File {} exists.'.format(target))
            print('Specify --force to overwrite. Aborting...')
            sys.exit()


def main():

    parser = argparse.ArgumentParser(description='')
    parser.add_argument('operation',
                        choices=(TO_SCREEPS, FROM_SCREEPS),
                        help='')
    parser.add_argument('destination', help='')
    parser.add_argument('--user', help='')
    parser.add_argument('--password', help='')
    parser.add_argument('--force', action='store_const', const=True,
                        help='force overwrite of files in an existing folder')
    parser.add_argument('--merge', action='store_const', const=True,
                        help='merge scripts into a single main.js module')

    args = parser.parse_args()

    user = args.user if args.user else get_user_from_env()
    password = args.password if args.password else get_password_from_env()

    target_folder = os.path.abspath(args.destination)

    if args.operation == FROM_SCREEPS:

        data = get_data(user, password)

        # does the folder exist?
        if not os.path.isdir(target_folder):

            # no - create it
            print('Creating new folder "{}"...'.format(target_folder))

            os.makedirs(target_folder)

        else:

            # yes - check for collisions (unless --force was specified)
            if not args.force:

                print('Checking for collisions...')

                check_for_collisions(target_folder, data['modules'])

                print('Ok, no collisions.')

        # for each module, create a corresponding filename and put it in
        # the target folder

        for module in data['modules']:

            target = os.path.join(target_folder, '{}.js'.format(module))

            with open(target, 'w') as fout:
                fout.write(data['modules'][module])

    else:

        modules = {}

        for root, folders, files in os.walk(target_folder):

            folders[:] = []

            for target_file in files:

                name, ext = os.path.splitext(target_file)

                if ext != '.js':
                    continue

                with open(os.path.join(root, target_file), 'r') as fin:
                    modules[name] = fin.read()

        if args.merge:

            merge_modules(modules)

        # upload modules
        send_data(user, password, modules)


def generate_header(filename):

    return '''
// {border}
// {name}
// {border}
'''.format(border='-' * 25, name=filename)


def merge_modules(modules):

    keys = [x for x in modules.keys()]

    keys.sort()

    merged = ''

    for key in keys:

        merged = merged + generate_header(key) + modules[key]

        del(modules[key])

    modules['main.js'] = merged

if __name__ == '__main__':

    main()

[((50, 11, 50, 41), 'os.environ.get', 'os.environ.get', ({(50, 26, 50, 40): '"""SCREEPS_USER"""'}, {}), "('SCREEPS_USER')", False, 'import os\n'), ((63, 15, 63, 49), 'os.environ.get', 'os.environ.get', ({(63, 30, 63, 48): '"""SCREEPS_PASSWORD"""'}, {}), "('SCREEPS_PASSWORD')", False, 'import os\n'), ((92, 11, 92, 40), 'requests.auth.HTTPBasicAuth', 'HTTPBasicAuth', ({(92, 25, 92, 29): 'user', (92, 31, 92, 39): 'password'}, {}), '(user, password)', False, 'from requests.auth import HTTPBasicAuth\n'), ((120, 13, 120, 52), 'argparse.ArgumentParser', 'argparse.ArgumentParser', (), '', False, 'import argparse\n'), ((137, 20, 137, 53), 'os.path.abspath', 'os.path.abspath', ({(137, 36, 137, 52): 'args.destination'}, {}), '(args.destination)', False, 'import os\n'), ((56, 8, 56, 18), 'sys.exit', 'sys.exit', ({}, {}), '()', False, 'import sys\n'), ((68, 8, 68, 18), 'sys.exit', 'sys.exit', ({}, {}), '()', False, 'import sys\n'), ((111, 11, 111, 33), 'os.path.exists', 'os.path.exists', ({(111, 26, 111, 32): 'target'}, {}), '(target)', False, 'import os\n'), ((176, 36, 176, 58), 'os.walk', 'os.walk', ({(176, 44, 176, 57): 'target_folder'}, {}), '(target_folder)', False, 'import os\n'), ((78, 33, 78, 62), 'requests.auth.HTTPBasicAuth', 'HTTPBasicAuth', ({(78, 47, 78, 51): 'user', (78, 53, 78, 61): 'password'}, {}), '(user, password)', False, 'from requests.auth import HTTPBasicAuth\n'), ((98, 30, 98, 46), 'json.dumps', 'json.dumps', ({(98, 41, 98, 45): 'data'}, {}), '(data)', False, 'import json\n'), ((115, 12, 115, 22), 'sys.exit', 'sys.exit', ({}, {}), '()', False, 'import sys\n'), ((144, 15, 144, 43), 'os.path.isdir', 'os.path.isdir', ({(144, 29, 144, 42): 'target_folder'}, {}), '(target_folder)', False, 'import os\n'), ((149, 12, 149, 38), 'os.makedirs', 'os.makedirs', ({(149, 24, 149, 37): 'target_folder'}, {}), '(target_folder)', False, 'import os\n'), ((182, 28, 182, 57), 'os.path.splitext', 'os.path.splitext', ({(182, 45, 182, 56): 'target_file'}, {}), '(target_file)', False, 'import os\n'), ((187, 26, 187, 57), 'os.path.join', 'os.path.join', ({(187, 39, 187, 43): 'root', (187, 45, 187, 56): 'target_file'}, {}), '(root, target_file)', False, 'import os\n')]