# 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__), "Multicall2_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 aggregate(self, calls: List) -> ContractFunction:
        return self.contract.functions.aggregate(calls)

    def blockAndAggregate(self, calls: List) -> ContractFunction:
        return self.contract.functions.blockAndAggregate(calls)

    def getBlockHash(self, blockNumber: int) -> ContractFunction:
        return self.contract.functions.getBlockHash(blockNumber)

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

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

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

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

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

    def getEthBalance(self, addr: ChecksumAddress) -> ContractFunction:
        return self.contract.functions.getEthBalance(addr)

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

    def tryAggregate(self, requireSuccess: bool, calls: List) -> ContractFunction:
        return self.contract.functions.tryAggregate(requireSuccess, calls)

    def tryBlockAndAggregate(
        self, requireSuccess: bool, calls: List
    ) -> ContractFunction:
        return self.contract.functions.tryBlockAndAggregate(requireSuccess, calls)


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)
