import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'lib'))
import base58
import hashlib
import re
from decimal import Decimal
import simplejson
import binascii
from misc import printdbg, epoch2str
import time


def is_valid_dynamic_address(address, network='mainnet'):
    # Only public key addresses are allowed
    # A valid address is a RIPEMD-160 hash which contains 20 bytes
    # Prior to base58 encoding 1 version byte is prepended and
    # 4 checksum bytes are appended so the total number of
    # base58 encoded bytes should be 25.  This means the number of characters
    # in the encoding should be about 34 ( 25 * log2( 256 ) / log2( 58 ) ).
    dynamic_version = 140 if network == 'testnet' else 76

    # Check length (This is important because the base58 library has problems
    # with long addresses (which are invalid anyway).
    if ((len(address) < 26) or (len(address) > 35)):
        return False

    address_version = None

    try:
        decoded = base58.b58decode_chk(address)
        address_version = ord(decoded[0:1])
    except:
        # rescue from exception, not a valid Dynamic address
        return False

    if (address_version != dynamic_version):
        return False

    return True


def hashit(data):
    return int(hashlib.sha256(data.encode('utf-8')).hexdigest(), 16)


# returns the dynode VIN of the elected winner
def elect_dn(**kwargs):
    current_block_hash = kwargs['block_hash']
    dn_list = kwargs['dnlist']

    # filter only enabled DNs
    enabled = [dn for dn in dn_list if dn.status == 'ENABLED']

    block_hash_hash = hashit(current_block_hash)

    candidates = []
    for dn in enabled:
        dn_vin_hash = hashit(dn.vin)
        diff = dn_vin_hash - block_hash_hash
        absdiff = abs(diff)
        candidates.append({'vin': dn.vin, 'diff': absdiff})

    candidates.sort(key=lambda k: k['diff'])

    try:
        winner = candidates[0]['vin']
    except:
        winner = None

    return winner


def parse_dynode_status_vin(status_vin_string):
    status_vin_string_regex = re.compile('CTxIn\(COutPoint\(([0-9a-zA-Z]+),\\s*(\d+)\),')

    m = status_vin_string_regex.match(status_vin_string)
    txid = m.group(1)
    index = m.group(2)

    vin = txid + '-' + index
    if (txid == '0000000000000000000000000000000000000000000000000000000000000000'):
        vin = None

    return vin