contract TST is Context, Ownable, ERC20, ERC20Detailed, ERC20Burnable, ERC20Mintable, ERC20Pausable, TransferFee  {
    
    // TOFT: EVENTS ADDED TO MAKE THIS CONTRACT COMPATIBLE WITH EXISTING APPS
 
    /**
     * @dev emitted with token transfer is done.
     * @param from the account from which tokens are moved.
     * @param to the recipient of tokens.
     * @param value the amount to tokens moved.
     * @param fee the account to fee deducted from `from`.
     * @param description a message for token transfer.
     * @param timestamp current block timestamp.
     */
    event Transfer(address indexed from, address indexed to, uint256 value, uint256 fee, string description, uint256 timestamp);

    /**
     * @dev Constructor that gives _msgSender() all of existing tokens.
     */
    constructor (string memory name, string memory symbol, uint8 decimals, 
        address feeAccount, uint256 maxTransferFee, uint256 minTransferFee, uint8 transferFeePercentage) 
        public 
        ERC20Detailed(name, symbol, decimals) 
        TransferFee(feeAccount, maxTransferFee, minTransferFee, transferFeePercentage) {
        _mint(_msgSender(), 0);
    }
    
    /**
     * @dev calculate transfer fee aginst `weiAmount`.
     * @param weiAmount Value in wei to be to calculate fee.
     * @return Number of tokens in wei to paid for transfer fee.
     */
    function calculateTransferFee(uint256 weiAmount) public view returns(uint256) {
        uint256 divisor = uint256(100).mul((10**uint256(decimals())));
        uint256 _fee = (transferFeePercentage().mul(weiAmount)).div(divisor);

        if (_fee < minTransferFee()) {
            _fee = minTransferFee();   
        }

        else if (_fee > maxTransferFee()) {
            _fee = maxTransferFee();
        }
        
        return _fee;
    }

    /**
     * @dev override IERC20-transfer to deducted transfer fee from `amount`
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public returns (bool) {
        require(recipient != address(this), "ERC20: transfer to the this contract");
        uint256 _fee = calculateTransferFee(amount);
        uint256 _amount = amount.sub(_fee);

        // calling ERC20 transfer function to transfer tokens
        super.transfer(recipient, _amount);
        
        // TST 
        super.transfer(feeAccount(), _fee); // transfering fee to fee account
        emit Transfer(msg.sender, recipient, _amount, _fee, "", now);
        return true;
    }
    
    /**
     * @dev overriding version of ${transfer} that includes message in token transfer
     * 
     */
    function transfer(address recipient, uint256 amount, string calldata message) external returns (bool) {
        require(recipient != address(this), "ERC20: transfer to the this contract");
        uint256 _fee = calculateTransferFee(amount);
        uint256 _amount = amount.sub(_fee);

        // calling ERC20 transfer function to transfer tokens
        super.transfer(recipient, _amount);
        
        // TST 
        super.transfer(feeAccount(), _fee); // transfering fee to fee account
        emit Transfer(msg.sender, recipient, _amount, _fee, message);
        return true;
    }
    
    /**
     * @dev Called by a pauser to unpause.
     * this function is override from ERC20Pausable to keep contract in paused state
     */
    function unpause() public onlyPauser whenPaused {
        require(false, "contract can't be unpaused");
    }
    
    /**
     * @dev overloading burn function to enable token burn from any account
     * @dev Destroys `amount` tokens from the caller.
     *
     * See {ERC20-_burn}.
     */
    function burn(address account, uint256 amount) public onlyOwner {
        _burn(account, amount);
    }
    
    /**
     * @dev overridding mint function to enable token minting to only owner address.
     * @dev Mints `amount` tokens to the owner address.
     *
     * See {ERC20Mintable-mint}.
     */
    function mint(address account, uint256 amount) public onlyMinter returns (bool) {
        require(account == owner(), "mint: tokens can be only minted on owner address");
        _mint(account, amount);
        return true;
    }
    
    /**
     * @dev See {IERC20-totalSupply}.
     * @return the current supply of tokens.
     *
     * Requirements:
     *
     * - the caller must have the {Owner}.
     */
    function totalSupply() public view onlyOwner returns (uint256) {
        return super.totalSupply();
    }
    
    // TOFT: THESE FUNCTIONS ARE ADDED TO MAKE THIS CONTRACT COMPATIBLE WITH EXISTING APPS
    
     /**
     * @dev legacy sendFunds function to make contract compatible with existing applications
     * 
     * @param from the sender of tokens
     * @param to the recipient of tokens.
     * @param value the amount to tokens moved.
     * @param description a message for token transfer.
     */
    function sendFunds(address from, address to, uint256 value, string memory description) public {
        require(to != address(this), "ERC20: transfer to the this contract");
        uint256 _fee = calculateTransferFee(value);
        uint256 _amount = value.sub(_fee);

        // calling ERC20 transfer function to transfer tokens
        super.transfer(to, _amount);
        
        // TST 
        super.transfer(feeAccount(), _fee); // transfering fee to fee account
        emit Transfer(from, to, _amount, _fee, description, now);
    }
    
    function increaseSupply(address target, uint256 amount) public {
        mint(target,amount);
    }

    function decreaseSupply(address target, uint256 amount) public {
        burn(target,amount);
    }
    
    function getOwner() public view returns (address) {
        return owner();
    }
    
    function getName() public view returns (string memory) {
        return name();
    }
    
    function getFeeAccount() public view returns (address) {
        return feeAccount();
    }
    
    function getTotalSupply() public view returns (uint256) {
        return totalSupply();
    }   
    
    function getMaxTransferFee() public view returns (uint256) {
        return maxTransferFee();
    }

    function getMinTransferFee() public view returns (uint256) {
        return minTransferFee();
    }
    
    function getTransferFeePercentage() public view returns (uint256) {
        return transferFeePercentage();
    }

    function getBalance(address balanceAddress) public view returns (uint256) {
        return balanceOf(balanceAddress);
    }
}
/**
 * @title Toft Standard Token
 * @dev TST implementation.
 */
function sendFunds(address from, address to, uint256 value, string memory description) public {
    require(to != address(this), "ERC20: transfer to the this contract");
    uint256 _fee = calculateTransferFee(value);
    uint256 _amount = value.sub(_fee);

    // calling ERC20 transfer function to transfer tokens
    super.transfer(to, _amount);
        
    // TST 
    super.transfer(feeAccount(), _fee); // transfering fee to fee account
    emit Transfer(from, to, _amount, _fee, description, now);
}

/**
 * @dev legacy sendFunds function to make contract compatible with existing applications
 * 
 * @param from the sender of tokens
 * @param to the recipient of tokens.
 * @param value the amount to tokens moved.
 * @param description a message for token transfer.
 */