#!/usr/bin/env python3
# Copyright (c) 2022 The Bitcoin Unlimited developers
import asyncio
from test_framework.util import assert_equal
from test_framework.electrumutil import (
    ElectrumTestFramework,
)
from test_framework.electrumconnection import ElectrumConnection
from test_framework.environment import on_nex, on_bch


class ElectrumTokenGenesisInfo(ElectrumTestFramework):
    async def run_test(self):
        # This test users nexad wallet to create and send tokens.
        # Mine and mature some coins.
        n = self.nodes[0]
        n.generate(120)

        cli = ElectrumConnection()
        await cli.connect()
        await self.sync_height(cli)
        try:
            await self.test_basic(n, cli)
            await self.test_with_token_history(n, cli)
            await self.test_decimal_places(n, cli)
            await self.test_genesis_minting_nft(n, cli)
        finally:
            cli.disconnect()

    async def test_basic(self, n, cli):
        addr = n.getnewaddress()

        if on_nex():
            ticker = "TICKER"
            name = "Some Name"
            url = "https://example.org"
            doc_hash = (
                "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
            )

            token_id, _ = await self.create_token(
                ticker, name, url, doc_hash, to_addr=addr, mint_amount=100
            )
        elif on_bch():
            token_id, _ = await self.create_token(to_addr=addr, mint_amount=100)
        else:
            raise NotImplementedError()

        # Get token info from mempool NYI for NEX
        n.generate(1)
        await self.sync_height(cli)

        info = await cli.call("token.genesis.info", token_id)
        assert "height" in info
        if on_nex():
            assert "txid" in info
            assert "txidem" in info
            assert_equal(token_id, info["group"])
            assert "token_id_hex" in info
            assert_equal(doc_hash, info["document_hash"])
            assert_equal(ticker, info["ticker"])
            assert_equal(name, info["name"])
            assert_equal(0, info["decimal_places"])
        if on_bch():
            assert "tx_hash" in info
            assert not "document_hash" in info
            assert not "ticker" in info
            assert not "name" in info
            assert_equal(None, info["bcmr"])

    async def test_with_token_history(self, n, cli):
        """
        Check that electrum is able to find genesis also when there are
        other token transactions within the same block as genesis transaction
        """
        if on_bch():
            # NYI - skip
            return

        addr = n.getnewaddress()

        token_id, _ = await self.create_token(
            "DUMMY", "dummy token", to_addr=addr, mint_amount=20
        )

        for _ in range(1, 20):
            n.token("send", token_id, addr, 10)

        n.generate(1)
        await self.sync_height(cli)
        info = await cli.call("token.genesis.info", token_id)
        assert_equal("DUMMY", info["ticker"])

        # Test subgroup genesis not returning parent genesis
        nft_id = self.create_nft(token_id, n.getnewaddress(), 24)
        assert nft_id != token_id
        n.generate(1)
        await self.sync_all(cli)
        nft_info = await cli.call("token.genesis.info", nft_id)
        assert_equal(nft_id, nft_info["group"])
        assert nft_info["ticker"] is None
        assert nft_info["token_id_hex"] != info["token_id_hex"]
        assert nft_info["height"] != info["height"]

    async def test_decimal_places(self, n, cli):
        if on_bch():
            # Not supported - skip
            return

        ticker = "TICKER"
        name = "Some Name"
        url = "https://example.org"
        doc_hash = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
        decimal_places = 11

        addr = n.getnewaddress()
        token_id_with_decimals, _ = await self.create_token(
            ticker, name, url, doc_hash, decimal_places, to_addr=addr, mint_amount=20
        )

        token_id_no_decimal, _ = await self.create_token(
            ticker, name, url, doc_hash, to_addr=addr, mint_amount=20
        )
        n.generate(1)
        await self.sync_height(cli)

        info = await cli.call("token.genesis.info", token_id_with_decimals)
        assert_equal(11, info["decimal_places"])
        info = await cli.call("token.genesis.info", token_id_no_decimal)
        assert_equal(0, info["decimal_places"])

    async def test_genesis_minting_nft(self, n, cli):
        """
        On BCH, a genesis transaction can mint NFT. Make sure it doesn't affect this API call.
        '"""
        if on_nex():
            # Genesis does not mint NFT
            return

        token_id, txid = await self.create_token(
            to_addr=n.getnewaddress(),
            mint_amount=42,
            bch_can_mint_nft=True,
        )
        await self.sync_mempool(cli)
        info = await cli.call("token.genesis.info", token_id)
        assert_equal(txid, info["tx_hash"])


if __name__ == "__main__":
    asyncio.run(ElectrumTokenGenesisInfo().main())
