#!/usr/bin/env python

from __future__ import print_function

import argparse
import json
import datetime

from moneywagon import CurrentPrice, HistoricalPrice, get_address_balance, get_historical_transactions

def datetime_to_iso(obj):
    """
    Python's default json encoder will blow up when it encounters datetime objects.
    So this work around is needed in order to just handle making datetime
    objects into iso8601 string format.
    """
    if isinstance(obj, datetime.datetime):
        serial = obj.isoformat()
        return serial
    raise TypeError ("Type not serializable")

parser = argparse.ArgumentParser() #version='1.0.2')

subparsers = parser.add_subparsers(help='commands', dest="subparser_name")

current_price_parser = subparsers.add_parser('current-price', help='Get current price of a crypto/fiat pair.')
current_price_parser.add_argument('crypto', action='store', help='Cryptocurrency symbol')
current_price_parser.add_argument('fiat', action='store', help='Fiat currency symbol')
current_price_parser.add_argument('--include-source', action='store_true', help='Return the source')
current_price_parser.add_argument('--verbose', action='store_true', help='Include extra output')

historical_price_parser = subparsers.add_parser('historical-price', help='Get price of a crypto/fiat pair at a point in time.')
historical_price_parser.add_argument('crypto', action='store', help='Cryptocurrency symbol')
historical_price_parser.add_argument('fiat', action='store', help='Fiat currency symbol')
historical_price_parser.add_argument('at_time', action='store', help='Time when to get the price. e.g. 2014-04-03')
historical_price_parser.add_argument('--verbose', action='store_true', help='Include extra output')

address_balance_parser = subparsers.add_parser('address-balance', help='Get total amount of coin in wallet.')
address_balance_parser.add_argument('crypto', action='store', help='Cryptocurrency symbol')
address_balance_parser.add_argument('address', action='store', help='Wallet address')
address_balance_parser.add_argument('--paranoid', action='store', help='How many services to use when cross-checking')
address_balance_parser.add_argument('--verbose', action='store_true', help='Include extra output')

historical_tx_parser = subparsers.add_parser('historical-transactions', help='Get list of all transactions for this address.')
historical_tx_parser.add_argument('crypto', action='store', help='Cryptocurrency symbol')
historical_tx_parser.add_argument('address', action='store', help='Wallet address')
historical_tx_parser.add_argument('--paranoid', action='store', help='How many services to use when cross-checking')
historical_tx_parser.add_argument('--verbose', action='store_true', help='Include extra output')

historical_tx_parser = subparsers.add_parser('wallet-balance', help='Get current value in fiat of a set of crypo addresses.')
historical_tx_parser.add_argument('wallet', type=argparse.FileType('r'), default=sys.stdin, help='Wallet file')
historical_tx_parser.add_argument('fiat', action='store', help='Fiat currency')
historical_tx_parser.add_argument('--paranoid', action='store', help='How many services to use when cross-checking')
historical_tx_parser.add_argument('--verbose', action='store_true', help='Include extra output')

argz = parser.parse_args()

if argz.subparser_name == 'current-price':
    price, source = CurrentPrice(verbose=argz.verbose).get(argz.crypto, argz.fiat)
    print(price, source if argz.include_source else '')

elif argz.subparser_name == 'historical-price':
    price, source, date = HistoricalPrice(verbose=argz.verbose).get(argz.crypto, argz.fiat, argz.at_time)
    print(price, source, date)

elif argz.subparser_name == 'address-balance':
    if argz.paranoid:
        mode = 'paranoid-%s' % argz.paranoid
    else:
        mode = 'default'

    print(get_address_balance(
        argz.crypto, argz.address, service_mode=mode, verbose=argz.verbose
    ))

elif argz.subparser_name == 'historical-transactions':
    if argz.paranoid:
        mode = 'paranoid-%s' % argz.paranoid
    else:
        mode = 'default'

    print(json.dumps(get_historical_transactions(
        argz.crypto, argz.address, service_mode=mode, verbose=argz.verbose
    ), default=datetime_to_iso))

elif argz.subparser_name == 'wallet-balance':
    current_price = CurrentPrice(verbose=argz.verbose) #defined here to cache api calls
    balance = AddressBalance(verbose=argz.verbose)
    wallets = argz.wallet
    fiat = argz.fiat.upper()

    cumm_amount = 0
    for line in wallets.readlines():
        if line.startswith("#"):
            continue

        currency, address = line.split(",")
        address = address.strip()
        try:
            price, price_source = current_price.get(currency, fiat)
        except Exception as exc:
            print("Can't get price for " + currency, exc)
            continue

        try:
            amount = balance.get(currency, address)
        except Exception as exc:
            print("Can't get balance for " + currency, exc)
            continue

        usd_amount = amount * price
        cumm_amount += usd_amount

        print(
            "%s (%.2f %s) == %s x %s (%s)" % (
                currency, usd_amount, fiat, amount, price, price_source
            )
        )

    print("Total amount of all crypto: %.2f %s" % (cumm_amount, fiat))
