contract BogToken is ERC20Pausable{
     
    uint256 private constant decimalFactor = 10**uint256(18);
    uint256 private _cap = uint256(18000000).mul(decimalFactor);
    
    uint256 private initialSupply = uint256(6000000).mul(decimalFactor);
    uint256 private mintRate = uint256(256).mul(decimalFactor);
    uint256 private constant MIN_MINT_RATE = uint256(2)*(decimalFactor);
    uint256 private bogdavaultInitialSupply = uint256(3000000).mul(decimalFactor);
    address public deployer;
    address public bogdavault;
    bool private _canMint = true;

    modifier onlyOwner(){
      require(msg.sender == deployer, "Address is not the owner");
      _;
    }
    
    modifier onlyBot(){
        require(msg.sender == bogdavault, "Address is nto the bot address");
        _;
    }
    

    
    constructor(address _bogdavault) public
    ERC20("BogToken", "BOG"){
      deployer = msg.sender;
      bogdavault = _bogdavault;
      _mint(msg.sender, initialSupply);
      _mint(bogdavault, bogdavaultInitialSupply);
    }
    

    //getter
    function bogdavaultSupply() public view returns(uint256){
      return balanceOf(bogdavault);
    }
    


    function remainingSupply() public view returns(uint256){
      return cap().sub(totalSupply());
    }
     
     
    function cap() public view returns(uint256){
        return _cap;
    }
    
    function burn(uint256 amount) public virtual {
        _burn(msg.sender, amount);
    }
    
    function burnFrom(address account, uint256 amount) public virtual {
        uint256 decreasedAllowance = allowance(account, msg.sender).sub(amount, "ERC20: burn amount exceeds allowance");

        _approve(account, msg.sender, decreasedAllowance);
        _burn(account, amount);
    }

    function relocateBogdavault(address _new) public onlyOwner{
      uint balance = balanceOf(bogdavault);
      transferFrom(bogdavault, _new, balance);
      bogdavault = _new;
    }

    function multipleBalanceOf(address[] memory accounts) public onlyOwner view returns(uint256[] memory){
        uint len = accounts.length;
        uint256[] memory balances =  new uint256[](len);
        for(uint i=0;i<len;i++){
            balances[i] = balanceOf(accounts[i]);
        }
        return balances;
    }
    
    function canMint() public view returns(bool){
        return _canMint;
    }

    //mint rate is halved each time updateMintRate() is called
    function updateMintRate() public onlyOwner{
        require(mintRate > MIN_MINT_RATE, "Minimum mint rate reached");
        mintRate = mintRate/2;
    }

    //rollback to previous mint rate
    function rollbackMintRate() public onlyOwner{
        mintRate = mintRate*2;
    }
    
    //set _canMint to true/false
    function toggleMint() public onlyOwner{
        _canMint = !_canMint;
    }

    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
        super._beforeTokenTransfer(from, to, amount);

        if (from == address(0)) { // When minting tokens
            require(totalSupply().add(amount) <= _cap, "ERC20Capped: cap exceeded");
        }
    }
    
    function _transfer(address from, address to, uint256 amount) internal override{
        if(canMint()){
            _mint(bogdavault, mintRate);
        }
        super._transfer(from,to,amount);
        

    }
    
}
function updateMintRate() public onlyOwner{
    require(mintRate > MIN_MINT_RATE, "Minimum mint rate reached");
    mintRate = mintRate/2;
}

//mint rate is halved each time updateMintRate() is called