# 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__), "ERC20_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(name: str, symbol: str) -> ContractConstructor:
        return ContractConstructor(name, symbol)

    def allowance(
        self, owner: ChecksumAddress, spender: ChecksumAddress
    ) -> ContractFunction:
        return self.contract.functions.allowance(owner, spender)

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

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

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

    def decreaseAllowance(
        self, spender: ChecksumAddress, subtractedValue: int
    ) -> ContractFunction:
        return self.contract.functions.decreaseAllowance(spender, subtractedValue)

    def increaseAllowance(
        self, spender: ChecksumAddress, addedValue: int
    ) -> ContractFunction:
        return self.contract.functions.increaseAllowance(spender, addedValue)

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

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

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

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

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

    def transferFrom(
        self, sender: ChecksumAddress, recipient: ChecksumAddress, amount: int
    ) -> ContractFunction:
        return self.contract.functions.transferFrom(sender, recipient, 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)
