contract FreezableMintableToken is MintableToken {

    mapping (address => bool) private frozenAccounts;

    // total frozen balance per address
    mapping (address => uint256) private frozenBalance;

    event FrozenAccount(address target, bool frozen);
    event TokensFrozen(address indexed account, uint amount);
    event TokensUnfrozen(address indexed account, uint amount);

    /**
     * @dev Freeze the specified address.
     * @param target The address to freeze.
     * @param freeze A boolean that indicates if this address is frozen or not.
     */
    function freezeAccount(address target, bool freeze) public onlyOwner {
        frozenAccounts[target] = freeze;
        emit FrozenAccount(target, freeze);
    }

    /**
     * @dev Gets the balance of frozen tokens at the specified address.
     */
    function frozenBalanceOf(address _owner) public view returns (uint256 balance) {
        return frozenBalance[_owner];
    }

    /**
     * @dev Gets the balance of the specified address which are not frozen and thus transferrable.
     * @param _owner The address to query the the balance of.
     * @return balance An uint256 representing the amount owned by the passed address.
     */
    function usableBalanceOf(address _owner) public view returns (uint256 balance) {
        return (balances[_owner].sub(frozenBalance[_owner]));
    }

    /**
     * @dev Send the specified amount of token to the specified address and freeze it.
     * @param _to Address to which token will be frozen.
     * @param _amount Amount of token to freeze.
     */
    function freezeTo(address _to, uint _amount) public onlyOwner {
        require(_to != address(0), "freezing a zero address");
        require(_amount <= balances[msg.sender], "amount exceeds balance");

        balances[msg.sender] = balances[msg.sender].sub(_amount);
        balances[_to] = balances[_to].add(_amount);
        frozenBalance[_to] = frozenBalance[_to].add(_amount);

        emit Transfer(msg.sender, _to, _amount);
        emit TokensFrozen(_to, _amount);
    }

    /**
     * @dev Unfreeze freezing tokens at the specified address.
     * @param _from Address from which frozen tokens are to be released.
     * @param _amount Amount of frozen tokens to release.
     */
    function unfreezeFrom(address _from, uint _amount) public onlyOwner {
        require(_from != address(0), "unfreezing from zero address");
        require(_amount <= frozenBalance[_from], "amount exceeds frozen balance");

        frozenBalance[_from] = frozenBalance[_from].sub(_amount);
        emit TokensUnfrozen(_from, _amount);
    }


    /**
     * @dev Mint the specified amount of token to the specified address and freeze it.
     * @param _to Address to which token will be frozen.
     * @param _amount Amount of token to mint and freeze.
     * @return A boolean that indicates if the operation was successful.
     */
    function mintAndFreeze(address _to, uint _amount) public onlyOwner canMint returns (bool) {
        totalSupply_ = totalSupply_.add(_amount);
        balances[_to] = balances[_to].add(_amount);
        frozenBalance[_to] = frozenBalance[_to].add(_amount);

        emit Mint(_to, _amount);
        emit TokensFrozen(_to, _amount);  
        emit Transfer(address(0), _to, _amount);
        return true;
    }  
    
    function transfer(address _to, uint256 _value) public override virtual returns (bool) {
        require(!frozenAccounts[msg.sender], "account is frozen");
        require(_value <= (balances[msg.sender].sub(frozenBalance[msg.sender])), 
            "amount exceeds usable balance");
        super.transfer(_to, _value);
    }

    function transferFrom(address _from, address _to, uint256 _value) public override virtual returns (bool) {
        require(!frozenAccounts[msg.sender], "account is frozen");
        require(_value <= (balances[_from].sub(frozenBalance[_from])), 
            "amount to transfer exceeds usable balance");
        super.transferFrom(_from, _to, _value);
    }

}
function freezeAccount(address target, bool freeze) public onlyOwner {
    frozenAccounts[target] = freeze;
    emit FrozenAccount(target, freeze);
}

/**
 * @dev Freeze the specified address.
 * @param target The address to freeze.
 * @param freeze A boolean that indicates if this address is frozen or not.
 */