# Code generated by moonworm : https://github.com/bugout-dev/moonworm
# Moonworm version : 0.2.4
import json
import os
from typing import Any, Dict, Union

from eth_typing.evm import Address, ChecksumAddress
from web3 import Web3
from web3.contract import ContractFunction

from .web3_util import *

abi_path = os.path.join(os.path.dirname(__file__), "Terminus_abi.json")
with open(abi_path, "r") as abi_file:
    CONTRACT_ABI = json.load(abi_file)


class Contract:
    def __init__(self, web3: Web3, contract_address: ChecksumAddress):
        self.web3 = web3
        self.address = contract_address
        self.contract = web3.eth.contract(address=self.address, abi=CONTRACT_ABI)

    @staticmethod
    def constructor() -> ContractConstructor:
        return ContractConstructor()

    def approveForPool(
        self, poolID: int, operator: ChecksumAddress
    ) -> ContractFunction:
        return self.contract.functions.approveForPool(poolID, operator)

    def balanceOf(self, account: ChecksumAddress, id: int) -> ContractFunction:
        return self.contract.functions.balanceOf(account, id)

    def balanceOfBatch(self, accounts: List, ids: List) -> ContractFunction:
        return self.contract.functions.balanceOfBatch(accounts, ids)

    def burn(
        self, from_: ChecksumAddress, poolID: int, amount: int
    ) -> ContractFunction:
        return self.contract.functions.burn(from_, poolID, amount)

    def contractURI(self) -> ContractFunction:
        return self.contract.functions.contractURI()

    def createPoolV1(
        self, _capacity: int, _transferable: bool, _burnable: bool
    ) -> ContractFunction:
        return self.contract.functions.createPoolV1(_capacity, _transferable, _burnable)

    def createSimplePool(self, _capacity: int) -> ContractFunction:
        return self.contract.functions.createSimplePool(_capacity)

    def isApprovedForAll(
        self, account: ChecksumAddress, operator: ChecksumAddress
    ) -> ContractFunction:
        return self.contract.functions.isApprovedForAll(account, operator)

    def isApprovedForPool(
        self, poolID: int, operator: ChecksumAddress
    ) -> ContractFunction:
        return self.contract.functions.isApprovedForPool(poolID, operator)

    def mint(
        self, to: ChecksumAddress, poolID: int, amount: int, data: bytes
    ) -> ContractFunction:
        return self.contract.functions.mint(to, poolID, amount, data)

    def mintBatch(
        self, to: ChecksumAddress, poolIDs: List, amounts: List, data: bytes
    ) -> ContractFunction:
        return self.contract.functions.mintBatch(to, poolIDs, amounts, data)

    def paymentToken(self) -> ContractFunction:
        return self.contract.functions.paymentToken()

    def poolBasePrice(self) -> ContractFunction:
        return self.contract.functions.poolBasePrice()

    def poolMintBatch(
        self, id: int, toAddresses: List, amounts: List
    ) -> ContractFunction:
        return self.contract.functions.poolMintBatch(id, toAddresses, amounts)

    def safeBatchTransferFrom(
        self,
        from_: ChecksumAddress,
        to: ChecksumAddress,
        ids: List,
        amounts: List,
        data: bytes,
    ) -> ContractFunction:
        return self.contract.functions.safeBatchTransferFrom(
            from_, to, ids, amounts, data
        )

    def safeTransferFrom(
        self,
        from_: ChecksumAddress,
        to: ChecksumAddress,
        id: int,
        amount: int,
        data: bytes,
    ) -> ContractFunction:
        return self.contract.functions.safeTransferFrom(from_, to, id, amount, data)

    def setApprovalForAll(
        self, operator: ChecksumAddress, approved: bool
    ) -> ContractFunction:
        return self.contract.functions.setApprovalForAll(operator, approved)

    def setContractURI(self, _contractURI: str) -> ContractFunction:
        return self.contract.functions.setContractURI(_contractURI)

    def setController(self, newController: ChecksumAddress) -> ContractFunction:
        return self.contract.functions.setController(newController)

    def setPaymentToken(self, newPaymentToken: ChecksumAddress) -> ContractFunction:
        return self.contract.functions.setPaymentToken(newPaymentToken)

    def setPoolBasePrice(self, newBasePrice: int) -> ContractFunction:
        return self.contract.functions.setPoolBasePrice(newBasePrice)

    def setPoolController(
        self, poolID: int, newController: ChecksumAddress
    ) -> ContractFunction:
        return self.contract.functions.setPoolController(poolID, newController)

    def setURI(self, poolID: int, poolURI: str) -> ContractFunction:
        return self.contract.functions.setURI(poolID, poolURI)

    def supportsInterface(self, interfaceId: bytes) -> ContractFunction:
        return self.contract.functions.supportsInterface(interfaceId)

    def terminusController(self) -> ContractFunction:
        return self.contract.functions.terminusController()

    def terminusPoolCapacity(self, poolID: int) -> ContractFunction:
        return self.contract.functions.terminusPoolCapacity(poolID)

    def terminusPoolController(self, poolID: int) -> ContractFunction:
        return self.contract.functions.terminusPoolController(poolID)

    def terminusPoolSupply(self, poolID: int) -> ContractFunction:
        return self.contract.functions.terminusPoolSupply(poolID)

    def totalPools(self) -> ContractFunction:
        return self.contract.functions.totalPools()

    def uri(self, poolID: int) -> ContractFunction:
        return self.contract.functions.uri(poolID)

    def withdrawPayments(
        self, toAddress: ChecksumAddress, amount: int
    ) -> ContractFunction:
        return self.contract.functions.withdrawPayments(toAddress, amount)


def deploy(
    web3: Web3,
    contract_constructor: ContractFunction,
    contract_bytecode: str,
    deployer_address: ChecksumAddress,
    deployer_private_key: str,
) -> Contract:
    tx_hash, contract_address = deploy_contract_from_constructor_function(
        web3,
        constructor=contract_constructor,
        contract_bytecode=contract_bytecode,
        contract_abi=CONTRACT_ABI,
        deployer=deployer_address,
        deployer_private_key=deployer_private_key,
    )
    return Contract(web3, contract_address)
