#!/usr/bin/env python3

# Copyright (C) 2017-2020 The btclib developers
#
# This file is part of btclib. It is subject to the license terms in the
# LICENSE file found in the top-level directory of this distribution.
#
# No part of btclib including this file, may be copied, modified, propagated,
# or distributed except according to the terms contained in the LICENSE file.

import unittest
from os import path
import json

from btclib import bip32, slip32
from btclib import electrum


class TestMnemonicDictionaries(unittest.TestCase):
    def test_mnemonic(self):
        lang = "en"

        entropy = 0x110AAAA03974D093EDA670121023CD0772
        eversion = "standard"
        # FIXME: is the following mnemonic obtained in Electrum
        # from the above entropy?
        mnemonic = (
            "ability awful fetch liberty company spatial "
            "panda hat then canal ball crouch bunker"
        )
        mnemonic2 = electrum.mnemonic_from_entropy(entropy, eversion, lang)
        self.assertEqual(mnemonic, mnemonic2)

        entr = int(electrum.entropy_from_mnemonic(mnemonic, lang), 2)
        self.assertLess(entr - entropy, 0xFFF)

        # mnemonic version not in electrum allowed mnemonic versions
        eversion = "std"
        self.assertRaises(
            ValueError, electrum.mnemonic_from_entropy, entropy, eversion, lang
        )
        # electrum.mnemonic_from_entropy(entropy, eversion, lang)

        # unknown electrum mnemonic version (00c)
        unknown_version = (
            "ability awful fetch liberty company spatial "
            "panda hat then canal ball cross video"
        )
        self.assertRaises(
            ValueError, electrum.entropy_from_mnemonic, unknown_version, lang
        )
        # electrum.entropy_from_mnemonic(unknown_version, lang)

        passphrase = ""

        # unknown electrum mnemonic version (00c)
        self.assertRaises(
            ValueError, bip32.mxprv_from_electrum_mnemonic, unknown_version, passphrase
        )
        # bip32.mxprv_from_electrum_mnemonic(mnemonic, passphrase)

        xprv = (
            "xprv9s21ZrQH143K2tn5j4pmrLXkS6dkbuX6mFhJfCxAwN6ofRo5ddCrLRWo"
            "gKEs1AptPmLgrthKxU2csfBgkoKECWtj1XMRicRsoWawukaRQft"
        )
        xprv2 = bip32.mxprv_from_electrum_mnemonic(mnemonic, passphrase)
        self.assertEqual(xprv2, xprv.encode())

        eversion = "2fa"
        mnemonic = electrum.mnemonic_from_entropy(entropy, eversion, lang)
        # 2fa mnemonic version is not managed yet
        self.assertRaises(
            ValueError, bip32.mxprv_from_electrum_mnemonic, mnemonic, passphrase
        )
        # bip32.mxprv_from_electrum_mnemonic(mnemonic, passphrase)

        eversion = "2fa_segwit"
        mnemonic = electrum.mnemonic_from_entropy(entropy, eversion, lang)
        # 2fa_segwit mnemonic version is not managed yet
        self.assertRaises(
            ValueError, bip32.mxprv_from_electrum_mnemonic, mnemonic, passphrase
        )
        # bip32.mxprv_from_electrum_mnemonic(mnemonic, passphrase)

    def test_vectors(self):
        fname = "electrum_test_vectors.json"
        filename = path.join(path.dirname(__file__), "test_data", fname)
        with open(filename, "r") as f:
            test_vectors = json.load(f)

        lang = "en"
        for test_vector in test_vectors:
            mnemonic = test_vector[0]
            passphrase = test_vector[1]
            mxprv = test_vector[2]
            mxpub = test_vector[3]
            address = test_vector[4]  # "./0/0"

            if mnemonic != "":
                mxprv2 = bip32.mxprv_from_electrum_mnemonic(mnemonic, passphrase)
                self.assertEqual(mxprv2, mxprv.encode())

                eversion, mnemonic = electrum.version_from_mnemonic(mnemonic)
                entr = int(electrum.entropy_from_mnemonic(mnemonic, lang), 2)
                mnem = electrum.mnemonic_from_entropy(entr, eversion, lang)
                self.assertEqual(mnem, mnemonic)

            if mxprv != "":
                mxpub2 = bip32.xpub_from_xprv(mxprv)
                self.assertEqual(mxpub2, mxpub.encode())

            xpub = bip32.derive(mxpub, "./0/0")
            address2 = slip32.address_from_xpub(xpub).decode("ascii")
            self.assertEqual(address2, address)

        # version 2fa_segwit
        mnemonic = (
            "slender flight session office noodle  hand "
            "couple  option office  wait   uniform morning"
        )
        self.assertEqual("2fa_segwit", electrum.version_from_mnemonic(mnemonic)[0])

        # version 2fa
        mnemonic = (
            "history recycle company awful donor   fold "
            "beef    nominee hard    bleak bracket six"
        )
        self.assertEqual("2fa", electrum.version_from_mnemonic(mnemonic)[0])


if __name__ == "__main__":
    # execute only if run as a script
    unittest.main()  # pragma: no cover
