from time import sleep, time

import bitcash
from bitcash.network.rates import (
    RatesAPI, bch_to_satoshi, currency_to_satoshi, currency_to_satoshi_cached,
    mbch_to_satoshi, satoshi_to_currency, satoshi_to_currency_cached,
    satoshi_to_satoshi, set_rate_cache_time, ubch_to_satoshi
)
from bitcash.utils import Decimal


def test_set_rate_cache_time():
    original = bitcash.network.rates.DEFAULT_CACHE_TIME
    set_rate_cache_time(30)
    updated = bitcash.network.rates.DEFAULT_CACHE_TIME

    assert original != updated
    assert updated == 30

    set_rate_cache_time(original)


def test_satoshi_to_satoshi():
    s = satoshi_to_satoshi()
    assert isinstance(s, int)
    assert s == 1


def test_ubch_to_satoshi():
    s = ubch_to_satoshi()
    assert isinstance(s, int)
    assert s == 100


def test_mbch_to_satoshi():
    s = mbch_to_satoshi()
    assert isinstance(s, int)
    assert s == 100000


def test_bch_to_satoshi():
    s = bch_to_satoshi()
    assert isinstance(s, int)
    assert s == 100000000


def test_currency_to_satoshi():
    assert currency_to_satoshi(1, 'usd') > currency_to_satoshi(1, 'jpy')


class TestSatoshiToCurrency:
    def test_no_exponent(self):
        assert satoshi_to_currency(1, 'bch') == '0.00000001'

    def test_zero_places(self):
        assert Decimal(satoshi_to_currency(100000, 'jpy')).as_tuple().exponent == 0


def test_satoshi_to_currency_cached():
    assert satoshi_to_currency_cached(1, 'ubch') == '0.01'


def test_rates_close():
    rates = sorted([
        api_call() for api_call in RatesAPI.USD_RATES
    ])
    # This is in tenths of a cent, so making sure they are within $10.
    assert rates[-1] - rates[0] < 10000


class TestRateCache:
    def test_cache(self):
        sleep(0.2)

        start_time = time()
        set_rate_cache_time(0)
        currency_to_satoshi_cached(1, 'usd')
        initial_time = time() - start_time

        start_time = time()
        set_rate_cache_time(60)
        currency_to_satoshi_cached(1, 'usd')
        cached_time = time() - start_time

        assert initial_time > cached_time

    def test_expires(self):
        sleep(0.2)

        set_rate_cache_time(0)
        currency_to_satoshi_cached(1, 'usd')

        start_time = time()
        set_rate_cache_time(60)
        currency_to_satoshi_cached(1, 'usd')
        cached_time = time() - start_time

        sleep(0.2)

        start_time = time()
        set_rate_cache_time(0.1)
        currency_to_satoshi_cached(1, 'usd')
        update_time = time() - start_time

        assert update_time > cached_time
