#!/usr/bin/env python

import argparse
import getpass
import sys
from binascii import hexlify

from ecdsa import SigningKey, SECP256k1

from cryptux.bitcoin import Account, Wallet
from cryptux.bitcoin.constants import MAINNET, TESTNET
from cryptux.bitcoin.constants import COMPRESSED, UNCOMPRESSED

# https://pymotw.com/2/getpass/
# https://github.com/pexpect/pexpect

if sys.version_info[0] == 2:
    input = raw_input


def bitcoin_addr_from_wif():
    '''Generate Bitcoin address by requesting WIF'''
    priv_key_wif = getpass.getpass(prompt='WIF for Private Key: ')
    account = Wallet.account_from_wif(priv_key_wif)
    return account.verbose_address


def input_net_type_key_fmt():
    '''Utility function to get network type & pub key format'''
    net_types = [MAINNET, TESTNET]
    key_formats = [COMPRESSED, UNCOMPRESSED]
    network_type, key_fmt = None, None
    while network_type not in net_types:
        network_type = input('Network type (%s): ' % '/'.join(net_types))
        network_type = network_type.upper()
    while key_fmt not in key_formats:
        key_fmt = input('Public key format (%s): ' % '/'.join(key_formats))
        key_fmt = key_fmt.upper()
    return (network_type, key_fmt)


def bitcoin_addr_from_hex():
    '''Generate Bitcoin address by requesting HEX data'''
    network_type, key_fmt = input_net_type_key_fmt()
    priv_key_hex = getpass.getpass(prompt='HEX for Private Key: ')
    account = Wallet.account_from_hex(priv_key_hex, network_type, key_fmt)
    return account.verbose_address


def bitcoin_addr_from_generator():
    '''Generate Private Key and then derive Bitcoin address'''
    network_type, key_fmt = input_net_type_key_fmt()
    account = Wallet.gen_account(network_type, key_fmt)
    priv_key_wif = account.wif
    priv_key_hex = account.hex.decode('utf-8')
    print('=' * 64)
    print('Remember to protect the Private Key!')
    print('=' * 32)
    print('Private Key in HEX: %s' % priv_key_hex)
    print('Private Key in WIF: %s' % priv_key_wif)
    return account.verbose_address


BITCOIN_GEN_HELPERS = {
    'WIF': bitcoin_addr_from_wif,
    'HEX': bitcoin_addr_from_hex,
    'NEW': bitcoin_addr_from_generator,
}


def gen_bitcoin_addr_helper():
    '''Helper to collect inputs for Bitcoin address'''
    str_priv_key_fmts = '/'.join(BITCOIN_GEN_HELPERS.keys())
    priv_key_fmt = None
    while priv_key_fmt not in BITCOIN_GEN_HELPERS:
        priv_key_fmt = input(
            'Private key format (%s): ' % str_priv_key_fmts)
        priv_key_fmt = priv_key_fmt.upper()
    bitcoin_addr, network_type, key_fmt = BITCOIN_GEN_HELPERS[priv_key_fmt]()
    print('=' * 64)
    print('Network type: %s' % network_type)
    print('Public key format: %s' % key_fmt)
    print('Generated Bitcoin address: %s' % bitcoin_addr)
    print('=' * 64)
    return bitcoin_addr


COIN_ADDR_HELPERS = {
    'BITCOIN': gen_bitcoin_addr_helper,
}

parser = argparse.ArgumentParser()
parser.add_argument(
    '-t',
    '--coin-type',
    type=str,
    help='coin type to generate account address for',
    choices=COIN_ADDR_HELPERS.keys())
args = parser.parse_args()
if not args.coin_type:
    parser.print_help()
    exit(0)
if args.coin_type not in COIN_ADDR_HELPERS:
    raise Exception('Unsupported coin type')
else:
    COIN_ADDR_HELPERS[args.coin_type]()
