import base58
from plenum.common.signer_did import DidSigner
from plenum.common.verifier import DidVerifier
from plenum.common.eventually import eventually
from plenum.test.helper import assertEquality

from sovrin.common.identity import Identity

MsgForSigning = {'sender': 'Mario', 'msg': 'Lorem ipsum'}


def signMsg(wallet, idr):
    return wallet.signMsg(MsgForSigning, identifier=idr)


def verifyMsg(verifier, sig):
    sig = base58.b58decode(sig)
    return verifier.verifyMsg(sig, MsgForSigning)


def chkVerifyForRetrievedIdentity(signerWallet, verifierWallet, idr):
    sig = signMsg(signerWallet, idr)
    verkey = verifierWallet.getIdentity(idr).verkey
    assert verifyMsg(DidVerifier(verkey, idr), sig)


def updateWalletIdrWithFullKeySigner(wallet, idr):
    newSigner = DidSigner(identifier=idr)
    wallet.updateSigner(idr, newSigner)
    assertEquality(newSigner.verkey, wallet.getVerkey(idr))
    checkFullVerkeySize(wallet.getVerkey(idr))
    return newSigner.verkey


def updateSovrinIdrWithFullKey(looper, senderWallet, senderClient, ownerWallet,
                               idr, fullKey):
    idy = Identity(identifier=idr, verkey=fullKey)
    senderWallet.updateSponsoredIdentity(idy)
    # TODO: What if the request fails, there must be some rollback mechanism
    assert senderWallet.getSponsoredIdentity(idr).seqNo is None
    reqs = senderWallet.preparePending()
    senderClient.submitReqs(*reqs)

    def chk():
        assert senderWallet.getSponsoredIdentity(idr).seqNo is not None

    looper.run(eventually(chk, retryWait=1, timeout=5))
    return ownerWallet


def fetchFullVerkeyFromSovrin(looper, senderWallet, senderClient, ownerWallet,
                               idr):
    identity = Identity(identifier=idr)
    req = senderWallet.requestIdentity(identity, sender=senderWallet.defaultId)
    senderClient.submitReqs(req)

    def chk():
        retrievedVerkey = senderWallet.getIdentity(idr).verkey
        assertEquality(retrievedVerkey, ownerWallet.getVerkey(idr))
        checkFullVerkeySize(retrievedVerkey)
    looper.run(eventually(chk, retryWait=1, timeout=5))


def checkDidSize(did):
    # A base58 encoding of 32 bytes string can be either 44 bytes or 43 bytes,
    # since the did takes first 16 bytes, base58 of did is either
    # 21 or 22 characters
    assert len(did) == 21 or len(did) == 22


def checkAbbrVerkeySize(verkey):
    # A base58 encoding of 32 bytes string can be either 44 bytes or 43 bytes,
    # since the abbreviated verkey takes last 16 bytes, base58 of abbreviated
    # verkey is either 21 or 22 characters and since its prefixed by a `~` its
    # length will be either 23 or 22
    assert len(verkey) == 23 or len(verkey) == 22


def checkFullVerkeySize(verkey):
    # A base58 encoding of 32 bytes string can be either 44 bytes or 43 bytes.
    assert len(verkey) == 44 or len(verkey) == 43

[((17, 10, 17, 31), 'base58.b58decode', 'base58.b58decode', ({(17, 27, 17, 30): 'sig'}, {}), '(sig)', False, 'import base58\n'), ((28, 16, 28, 41), 'plenum.common.signer_did.DidSigner', 'DidSigner', (), '', False, 'from plenum.common.signer_did import DidSigner\n'), ((37, 10, 37, 50), 'sovrin.common.identity.Identity', 'Identity', (), '', False, 'from sovrin.common.identity import Identity\n'), ((53, 15, 53, 39), 'sovrin.common.identity.Identity', 'Identity', (), '', False, 'from sovrin.common.identity import Identity\n'), ((24, 21, 24, 45), 'plenum.common.verifier.DidVerifier', 'DidVerifier', ({(24, 33, 24, 39): 'verkey', (24, 41, 24, 44): 'idr'}, {}), '(verkey, idr)', False, 'from plenum.common.verifier import DidVerifier\n'), ((47, 15, 47, 54), 'plenum.common.eventually.eventually', 'eventually', (), '', False, 'from plenum.common.eventually import eventually\n'), ((61, 15, 61, 54), 'plenum.common.eventually.eventually', 'eventually', (), '', False, 'from plenum.common.eventually import eventually\n')]