contract SwapBloexToken is ERC20, ERC20Detailed {
    using SafeERC20 for IERC20;
    using Address for address;
    using SafeMath for uint;
    
    IERC20 public btToken;   
    IERC20 public usdtToken;
    address public governance;

    uint8 public isOpenDeposit = 1;
    uint8 public isOpenWithdraw = 1;
    
    uint public btRate = 2230;              //bt founding value
    uint constant public rateBase = 10000; 

    address constant public usdt = address(0xdAC17F958D2ee523a2206206994597C13D831ec7);      //Tether USD (USDT)
    address constant public bt = address(0x061C266cAF366e73CeA4bdc9DC22392fb81115F2);             //Bloex Token (BT) 


    constructor () public ERC20Detailed("BloexSwap", "BTSwap", 18) {
        btToken = IERC20(bt);
        usdtToken = IERC20(usdt);
        governance = 0x1360CFA0606E5b057df468D540fA81F75d8146E3;
    }
    
    function setGovernance(address _governance) public {
        require(msg.sender == governance, "!governance");
        governance = _governance;
    }
    
    //set bt founding value
    function setBTRate(uint _btRate) external {
        require(msg.sender == governance, "!governance");
        btRate = _btRate;
    }
    
    function setOpenDeposit(uint8 _isOpenDeposit) external {
        require(msg.sender == governance, "!governance");
        isOpenDeposit = _isOpenDeposit;
    }
    function setOpenWithdraw(uint8 _isOpenWithdraw) external {
        require(msg.sender == governance, "!governance");
        isOpenWithdraw = _isOpenWithdraw;
    }


    //buy bt with usdt
    function deposit(uint _amount) public {
        require(isOpenDeposit == 1, "!isOpenDeposit");

        // Check usdt balance
        require(_amount <= usdtToken.balanceOf(msg.sender), "!sufficient USDT");

        //get bt amount
        uint bt_amount = _amount.mul(rateBase).div(btRate).mul(1e12);  //18 decimals
        
        // Check bt balance
        require(bt_amount <= btToken.balanceOf(address(this)), "!sufficient BT");        

        //deposit usdt
        usdtToken.safeTransferFrom(msg.sender, address(this), _amount);

        //pay bt
        btToken.safeTransfer(msg.sender, bt_amount);
    }
    
    //swap bt to usdt
    function withdraw(uint _amount) public {
        require(isOpenWithdraw == 1, "!isOpenWithdraw");
        
        // Check bt balance
        require(_amount <= btToken.balanceOf(msg.sender), "!sufficient BT");
        
        //swap back usdt amount
        uint usdt_amount = _amount.mul(btRate).div(rateBase).div(1e12);  //6 decimals
        
        // Check usdt balance
        require(usdt_amount <= usdtToken.balanceOf(address(this)), "!sufficient USDT");
        
        //withdraw bt
        btToken.safeTransferFrom(msg.sender, address(this), _amount);

        //pay usdt
        usdtToken.safeTransfer(msg.sender, usdt_amount);
    }
    
    function depositAll() external {
        require(isOpenDeposit == 1, "!isOpenDeposit");
        
        deposit(usdtToken.balanceOf(msg.sender));
    }
    
    function withdrawAll() external {
        require(isOpenWithdraw == 1, "!isOpenWithdraw");
        
        withdraw(balanceOf(msg.sender));
    }
    
    function moveUSDT() public {
        require(msg.sender == governance, "!governance");
        uint _amount = usdtToken.balanceOf(address(this));
        usdtToken.safeTransfer(msg.sender, _amount);
    }
    
    function moveBT() public {
        require(msg.sender == governance, "!governance");
        uint _amount = btToken.balanceOf(address(this));
        btToken.safeTransfer(msg.sender, _amount);
    }

    //bt balanceOf
    function balanceOf(address _owner) public view returns (uint256) {
        return btToken.balanceOf(_owner);

    }
    
    function inCaseTokensGetStuck(address _token, uint _amount) public {
      //any erc20
      require(msg.sender == governance, "!governance");
      IERC20(_token).safeTransfer(governance, _amount);
    }
    
    function getPricePerFullShare() public view returns (uint) {
      return btRate.mul(1e18).div(rateBase);
    }
}
function withdraw(uint _amount) public {
    require(isOpenWithdraw == 1, "!isOpenWithdraw");
        
    // Check bt balance
    require(_amount <= btToken.balanceOf(msg.sender), "!sufficient BT");
        
    //swap back usdt amount
    uint usdt_amount = _amount.mul(btRate).div(rateBase).div(1e12);  //6 decimals
        
    // Check usdt balance
    require(usdt_amount <= usdtToken.balanceOf(address(this)), "!sufficient USDT");
        
    //withdraw bt
    btToken.safeTransferFrom(msg.sender, address(this), _amount);

    //pay usdt
    usdtToken.safeTransfer(msg.sender, usdt_amount);
}

//swap bt to usdt