#!python
import argparse
import json
import os
import sys
import vyper
import warnings

from collections import OrderedDict
from argparse import RawTextHelpFormatter
from vyper.parser import parser_utils


warnings.simplefilter('always')
sys.tracebacklimit = 0
tb_limit = os.environ.get('VYPER_TRACEBACK_LIMIT')
if tb_limit:
    sys.tracebacklimit = int(tb_limit)

format_options_help = """Format to print, one or more of:
 bytecode (default) - Deployable bytecode
 bytecode_runtime   - Bytecode at runtime
 abi                - ABI in JSON format
 abi_python         - ABI in Python format
 ir                 - Vyper IR (a dialect of LLL)
 asm                - EVM Assembly
 source_map         - Vyper source map
 method_identifiers - Dictionary of method signature to method identifier.
 combined_json      - All of the above format options combined as single JSON output.
"""

parser = argparse.ArgumentParser(
    description='Vyper programming language for Ethereum',
    formatter_class=RawTextHelpFormatter
)
parser.add_argument('input_files', help='Vyper sourcecode to compile', nargs='+')
parser.add_argument('--version', action='version', version='{0}'.format(vyper.__version__))
parser.add_argument('--show-gas-estimates', help='Show gas estimates in ir output mode.', action="store_true")
parser.add_argument('-f', help=format_options_help, default='bytecode', dest='format')

args = parser.parse_args()


def uniq(seq):
    exists = set()
    return [x for x in seq if not (x in exists or exists.add(x))]


def exc_handler(contract_name, exception):
    print('Error compiling: ', contract_name)
    raise exception


if __name__ == '__main__':

    if args.show_gas_estimates:
        parser_utils.LLLnode.repr_show_gas = True

    codes = OrderedDict()
    for file_name in args.input_files:
        with open(file_name) as fh:
            codes[file_name] = fh.read()

    # Combined json output
    if args.format == 'combined_json':
        out = vyper.compile_codes(
            codes,
            ['bytecode', 'bytecode_runtime', 'abi', 'source_map', 'method_identifiers'],
            output_type='dict',
            exc_handler=exc_handler
        )
        out['version'] = vyper.__version__
        print(json.dumps(out))

    else:  # Normal output.
        translate_map = {
            'abi_python': 'abi',
            'json': 'abi'
        }
        formats = []
        orig_args = uniq(args.format.split(','))
        for f in orig_args:
            formats.append(translate_map.get(f, f))

        out_list = vyper.compile_codes(codes, formats, output_type='list', exc_handler=exc_handler)
        for out in out_list:
            for f in orig_args:
                o = out[translate_map.get(f, f)]
                if f in ('abi', 'json'):
                    print(json.dumps(o))
                elif f == 'abi_python':
                    print(o)
                elif f == 'source_map':
                    print(json.dumps(o))
                else:
                    print(o)
