import logging
log = logging.getLogger('marketagents')

from enforce_typing import enforce_types # type: ignore[import]
import random

from agents.PublisherAgent import PublisherAgent
from agents.PoolAgent import PoolAgent
from util import constants
from util.constants import POOL_WEIGHT_DT, POOL_WEIGHT_OCEAN
from web3engine import bfactory, bpool, datatoken, dtfactory, globaltokens
from web3tools.web3util import toBase18
        
@enforce_types
class EWPublisherAgent(PublisherAgent):
    def __init__(self, name: str, USD: float, OCEAN: float):
        super().__init__(name, USD, OCEAN)
        
        self._s_since_create = 0
        self._s_between_create = 7 * constants.S_PER_DAY #magic number
        
        self._s_since_unstake = 0
        self._s_between_unstake = 3 * constants.S_PER_DAY #magic number
        
    def takeStep(self, state) -> None:
        self._s_since_create += state.ss.time_step
        self._s_since_unstake += state.ss.time_step
        
        if self._doCreatePool():
            self._s_since_create = 0
            self._createPoolAgent(state)

        if self._doUnstakeOCEAN(state):
            self._s_since_unstake = 0
            self._unstakeOCEANsomewhere(state)

    def _doCreatePool(self) -> bool:
        if self.OCEAN() < 200.0: #magic number
            return False
        return self._s_since_create >= self._s_between_create

    def _createPoolAgent(self, state) -> PoolAgent:        
        assert self.OCEAN() > 0.0, "should not call if no OCEAN"
        wallet = self._wallet._web3wallet
        OCEAN = globaltokens.OCEANtoken()
        
        #name
        pool_i = len(state.agents.filterToPool())
        dt_name = f'DT{pool_i}'
        pool_agent_name = f'pool{pool_i}'
        
        #new DT
        DT = self._createDatatoken(dt_name, mint_amt=1000.0) #magic number

        #new pool
        pool_address = bfactory.BFactory().newBPool(from_wallet=wallet)
        pool = bpool.BPool(pool_address)

        #bind tokens & add initial liquidity
        OCEAN_bind_amt = self.OCEAN() #magic number: use all the OCEAN
        DT_bind_amt = 20.0 #magic number
                
        DT.approve(pool.address, toBase18(DT_bind_amt), from_wallet=wallet)
        OCEAN.approve(pool.address, toBase18(OCEAN_bind_amt),from_wallet=wallet)
        
        pool.bind(DT.address, toBase18(DT_bind_amt),
                  toBase18(POOL_WEIGHT_DT), from_wallet=wallet)
        pool.bind(OCEAN.address, toBase18(OCEAN_bind_amt),
                  toBase18(POOL_WEIGHT_OCEAN), from_wallet=wallet)
        
        pool.finalize(from_wallet=wallet)

        #create agent
        pool_agent = PoolAgent(pool_agent_name, pool)
        state.addAgent(pool_agent)
        
        return pool_agent

    def _doUnstakeOCEAN(self, state) -> bool:
        if not state.agents.filterByNonzeroStake(self):
            return False
        return self._s_since_unstake >= self._s_between_unstake

    def _unstakeOCEANsomewhere(self, state):
        """Choose what pool to unstake and by how much. Then do the action."""
        pool_agents = state.agents.filterByNonzeroStake(self)
        pool_agent = random.choice(list(pool_agents.values()))
        BPT = self.BPT(pool_agent.pool)
        BPT_unstake = 0.10 * BPT #magic number
        self.unstakeOCEAN(BPT_unstake, pool_agent.pool)

    def _createDatatoken(self,dt_name:str,mint_amt:float)-> datatoken.Datatoken:
        """Create datatoken contract and mint DTs to self."""
        wallet = self._wallet._web3wallet
        DT_address = dtfactory.DTFactory().createToken(
            '', dt_name, dt_name, toBase18(mint_amt), from_wallet=wallet)
        DT = datatoken.Datatoken(DT_address)
        DT.mint(wallet.address, toBase18(mint_amt), from_wallet=wallet)
        return DT

[((2, 6, 2, 39), 'logging.getLogger', 'logging.getLogger', ({(2, 24, 2, 38): '"""marketagents"""'}, {}), "('marketagents')", False, 'import logging\n'), ((45, 16, 45, 41), 'web3engine.globaltokens.OCEANtoken', 'globaltokens.OCEANtoken', ({}, {}), '()', False, 'from web3engine import bfactory, bpool, datatoken, dtfactory, globaltokens\n'), ((57, 15, 57, 40), 'web3engine.bpool.BPool', 'bpool.BPool', ({(57, 27, 57, 39): 'pool_address'}, {}), '(pool_address)', False, 'from web3engine import bfactory, bpool, datatoken, dtfactory, globaltokens\n'), ((74, 21, 74, 53), 'agents.PoolAgent.PoolAgent', 'PoolAgent', ({(74, 31, 74, 46): 'pool_agent_name', (74, 48, 74, 52): 'pool'}, {}), '(pool_agent_name, pool)', False, 'from agents.PoolAgent import PoolAgent\n'), ((97, 13, 97, 44), 'web3engine.datatoken.Datatoken', 'datatoken.Datatoken', ({(97, 33, 97, 43): 'DT_address'}, {}), '(DT_address)', False, 'from web3engine import bfactory, bpool, datatoken, dtfactory, globaltokens\n'), ((63, 33, 63, 54), 'web3tools.web3util.toBase18', 'toBase18', ({(63, 42, 63, 53): 'DT_bind_amt'}, {}), '(DT_bind_amt)', False, 'from web3tools.web3util import toBase18\n'), ((64, 36, 64, 60), 'web3tools.web3util.toBase18', 'toBase18', ({(64, 45, 64, 59): 'OCEAN_bind_amt'}, {}), '(OCEAN_bind_amt)', False, 'from web3tools.web3util import toBase18\n'), ((66, 30, 66, 51), 'web3tools.web3util.toBase18', 'toBase18', ({(66, 39, 66, 50): 'DT_bind_amt'}, {}), '(DT_bind_amt)', False, 'from web3tools.web3util import toBase18\n'), ((67, 18, 67, 42), 'web3tools.web3util.toBase18', 'toBase18', ({(67, 27, 67, 41): 'POOL_WEIGHT_DT'}, {}), '(POOL_WEIGHT_DT)', False, 'from web3tools.web3util import toBase18\n'), ((68, 33, 68, 57), 'web3tools.web3util.toBase18', 'toBase18', ({(68, 42, 68, 56): 'OCEAN_bind_amt'}, {}), '(OCEAN_bind_amt)', False, 'from web3tools.web3util import toBase18\n'), ((69, 18, 69, 45), 'web3tools.web3util.toBase18', 'toBase18', ({(69, 27, 69, 44): 'POOL_WEIGHT_OCEAN'}, {}), '(POOL_WEIGHT_OCEAN)', False, 'from web3tools.web3util import toBase18\n'), ((96, 34, 96, 52), 'web3tools.web3util.toBase18', 'toBase18', ({(96, 43, 96, 51): 'mint_amt'}, {}), '(mint_amt)', False, 'from web3tools.web3util import toBase18\n'), ((98, 32, 98, 50), 'web3tools.web3util.toBase18', 'toBase18', ({(98, 41, 98, 49): 'mint_amt'}, {}), '(mint_amt)', False, 'from web3tools.web3util import toBase18\n'), ((56, 23, 56, 42), 'web3engine.bfactory.BFactory', 'bfactory.BFactory', ({}, {}), '()', False, 'from web3engine import bfactory, bpool, datatoken, dtfactory, globaltokens\n'), ((95, 21, 95, 42), 'web3engine.dtfactory.DTFactory', 'dtfactory.DTFactory', ({}, {}), '()', False, 'from web3engine import bfactory, bpool, datatoken, dtfactory, globaltokens\n')]