# Path: keepkeylib/tools.py
# def b58decode(v, length):
#     """ decode v into a string of len bytes."""
#     long_value = 0
#     for (i, c) in enumerate(v[::-1]):
#         long_value += __b58chars.find(c) * (__b58base ** i)
# 
#     result = b''
#     while long_value >= 256:
#         div, mod = divmod(long_value, 256)
#         result = struct.pack('B', mod) + result
#         long_value = div
#     result = struct.pack('B', long_value) + result
# 
#     nPad = 0
#     for c in v:
#         if c == __b58chars[0]:
#             nPad += 1
#         else:
#             break
# 
#     result = b'\x00' * nPad + result
#     if length is not None and len(result) != length:
#         return None
# 
#     return result
# 
# def b58encode(v):
#     """ encode v, which is a string of bytes, to base58."""
# 
#     long_value = 0
#     for c in iterbytes(v):
#         long_value = long_value * 256 + c
# 
#     result = ''
#     while long_value >= __b58base:
#         div, mod = divmod(long_value, __b58base)
#         result = __b58chars[mod] + result
#         long_value = div
#     result = __b58chars[long_value] + result
# 
#     # Bitcoin does a little leading-zero-compression:
#     # leading 0-bytes in the input become leading-1s
#     nPad = 0
#     for c in iterbytes(v):
#         if c == 0:
#             nPad += 1
#         else:
#             break
# 
#     return (__b58chars[0] * nPad) + result
# 
# def parse_path(nstr):
#     """
#     Convert BIP32 path string to list of uint32 integers with hardened flags.
#     Several conventions are supported to set the hardened flag: -1, 1', 1h
#     e.g.: "0/1h/1" -> [0, 0x80000001, 1]
#     :param nstr: path string
#     :return: list of integers
#     """
#     if not nstr:
#         return []
# 
#     n = nstr.split('/')
# 
#     # m/a/b/c => a/b/c
#     if n[0] == 'm':
#         n = n[1:]
# 
#     # coin_name/a/b/c => 44'/SLIP44_constant'/a/b/c
#     #if n[0] in slip44:
#     #    coin_id = slip44[n[0]]
#     #    n[0:1] = ['44h', '{}h'.format(coin_id)]
# 
#     def str_to_harden(x):
#         if x.startswith('-'):
#             return H_(abs(int(x)))
#         elif x.endswith(('h', "'")):
#             return H_(int(x[:-1]))
#         else:
#             return int(x)
# 
#     try:
#         return list(str_to_harden(x) for x in n)
#     except Exception:
#         raise ValueError('Invalid BIP32 path', nstr)
# 
# def int_to_big_endian(value):
#     import struct
# 
#     res = b''
#     while 0 < value:
#         res = struct.pack("B", value & 0xff) + res
#         value = value >> 8
# 
#     return res


import hashlib
import binascii
import struct
from datetime import datetime
from .tools import b58decode, b58encode, parse_path, int_to_big_endian
from . import messages_eos_pb2 as proto
    _t = 0
    if pub_key[:3] == 'EOS':
        pub_key = pub_key[3:]
        _t = 0
    elif pub_key[:7] == 'PUB_K1_':
        pub_key = pub_key[7:]
        _t = 0
    elif pub_key[:7] == 'PUB_R1_':
        pub_key = pub_key[7:]
        _t = 1

    return _t, b58decode(pub_key, None)[:-4]

def h160(public_key):
    md = hashlib.new('ripemd160')
    md.update(public_key)
    return md.digest()

def public_key_to_wif(pub_key, prefix):
    if len(pub_key) == 65:
        head = 0x03 if (pub_key[64] & 0x01) == 1 else 0x02
        compressed_pub_key = bytes([head]) + pub_key[1:33]
    elif len(pub_key) == 33:
        compressed_pub_key = pub_key
    else:
        raise Exception("invalid public key length")
    return prefix + b58encode(compressed_pub_key + h160(compressed_pub_key)[:4])

def encode_signature(prefix, v, r, s, keyType):
    sig = struct.pack("B", v) + r + s

# Path: keepkeylib/tools.py
# def b58decode(v, length):
#     """ decode v into a string of len bytes."""
#     long_value = 0
#     for (i, c) in enumerate(v[::-1]):
#         long_value += __b58chars.find(c) * (__b58base ** i)
# 
#     result = b''
#     while long_value >= 256:
#         div, mod = divmod(long_value, 256)
#         result = struct.pack('B', mod) + result
#         long_value = div
#     result = struct.pack('B', long_value) + result
# 
#     nPad = 0
#     for c in v:
#         if c == __b58chars[0]:
#             nPad += 1
#         else:
#             break
# 
#     result = b'\x00' * nPad + result
#     if length is not None and len(result) != length:
#         return None
# 
#     return result
# 
# def b58encode(v):
#     """ encode v, which is a string of bytes, to base58."""
# 
#     long_value = 0
#     for c in iterbytes(v):
#         long_value = long_value * 256 + c
# 
#     result = ''
#     while long_value >= __b58base:
#         div, mod = divmod(long_value, __b58base)
#         result = __b58chars[mod] + result
#         long_value = div
#     result = __b58chars[long_value] + result
# 
#     # Bitcoin does a little leading-zero-compression:
#     # leading 0-bytes in the input become leading-1s
#     nPad = 0
#     for c in iterbytes(v):
#         if c == 0:
#             nPad += 1
#         else:
#             break
# 
#     return (__b58chars[0] * nPad) + result
# 
# def parse_path(nstr):
#     """
#     Convert BIP32 path string to list of uint32 integers with hardened flags.
#     Several conventions are supported to set the hardened flag: -1, 1', 1h
#     e.g.: "0/1h/1" -> [0, 0x80000001, 1]
#     :param nstr: path string
#     :return: list of integers
#     """
#     if not nstr:
#         return []
# 
#     n = nstr.split('/')
# 
#     # m/a/b/c => a/b/c
#     if n[0] == 'm':
#         n = n[1:]
# 
#     # coin_name/a/b/c => 44'/SLIP44_constant'/a/b/c
#     #if n[0] in slip44:
#     #    coin_id = slip44[n[0]]
#     #    n[0:1] = ['44h', '{}h'.format(coin_id)]
# 
#     def str_to_harden(x):
#         if x.startswith('-'):
#             return H_(abs(int(x)))
#         elif x.endswith(('h', "'")):
#             return H_(int(x[:-1]))
#         else:
#             return int(x)
# 
#     try:
#         return list(str_to_harden(x) for x in n)
#     except Exception:
#         raise ValueError('Invalid BIP32 path', nstr)
# 
# def int_to_big_endian(value):
#     import struct
# 
#     res = b''
#     while 0 < value:
#         res = struct.pack("B", value & 0xff) + res
#         value = value >> 8
# 
#     return res


# Path: keepkeylib/eos.py
import hashlib
import binascii
import struct
from datetime import datetime
from .tools import b58decode, b58encode, parse_path, int_to_big_endian
from . import messages_eos_pb2 as proto

    _t = 0
    if pub_key[:3] == 'EOS':
        pub_key = pub_key[3:]
        _t = 0
    elif pub_key[:7] == 'PUB_K1_':
        pub_key = pub_key[7:]
        _t = 0
    elif pub_key[:7] == 'PUB_R1_':
        pub_key = pub_key[7:]
        _t = 1

    return _t, b58decode(pub_key, None)[:-4]

def h160(public_key):
    md = hashlib.new('ripemd160')
    md.update(public_key)
    return md.digest()

def public_key_to_wif(pub_key, prefix):
    if len(pub_key) == 65:
        head = 0x03 if (pub_key[64] & 0x01) == 1 else 0x02
        compressed_pub_key = bytes([head]) + pub_key[1:33]
    elif len(pub_key) == 33:
        compressed_pub_key = pub_key
    else:
        raise Exception("invalid public key length")
    return prefix + b58encode(compressed_pub_key + h160(compressed_pub_key)[:4])

def encode_signature(prefix, v, r, s, keyType):
    sig = struct.pack("B", v) + r + s

    return prefix + b58encode(sig + h160(sig + keyType)[:4])