contract ERC777RemoteBridge is ERC777 {

    CStore public balancesDB;

    constructor(
        string memory _name,
        string memory _symbol,
        uint256 _granularity,
        uint256 _totalSupply,
        address _initialOwner,
        address[] memory _defaultOperators
    )
    public ERC777(_name, _symbol, _granularity, new address[](0))
    {
        balancesDB = new CStore(_totalSupply, _initialOwner, _defaultOperators);
    }

    /**
     * @return the total supply of the token
     */
    function totalSupply() public view returns (uint256) {
        return balancesDB.getTotalSupply();
    }

    /**
     * @notice Return the account balance of some account
     * @param _tokenHolder Address for which the balance is returned
     * @return the balance of `_tokenAddress`.
     */
    function balanceOf(address _tokenHolder) public view returns (uint256) {
        return balancesDB.getBalance(_tokenHolder);
    }

    /**
     * @notice Return the list of default operators
     * @return the list of all the default operators
     */
    function defaultOperators() public view returns (address[] memory) {
        return balancesDB.getDefaultOperators();
    }

    /**
     * @notice Authorize a third party `_operator` to manage (send) `msg.sender`'s tokens at remote database.
     * @param _operator The operator that wants to be Authorized
     */
    function authorizeOperator(address _operator) external {
        require(_operator != msg.sender, "Cannot authorize yourself as an operator");
        if (balancesDB.getDefaultOperator(_operator)) {
            require(balancesDB.setRevokedDefaultOperator(_operator, msg.sender, false));
        } else {
            require(balancesDB.setAuthorizedOperator(_operator, msg.sender, true));
        }
        emit AuthorizedOperator(_operator, msg.sender);
    }

    /**
     * @notice Revoke a third party `_operator`'s rights to manage (send) `msg.sender`'s tokens at remote database.
     * @param _operator The operator that wants to be Revoked
     */
    function revokeOperator(address _operator) external {
        require(_operator != msg.sender, "Cannot revoke yourself as an operator");
        if (balancesDB.getDefaultOperator(_operator)) {
            require(balancesDB.setRevokedDefaultOperator(_operator, msg.sender, true));
        } else {
            require(balancesDB.setAuthorizedOperator(_operator, msg.sender, false));
        }
        emit RevokedOperator(_operator, msg.sender);
    }

    /**
    * @notice Check whether the `_operator` address is allowed to manage the tokens held by `_tokenHolder`
    *  address at remote database.
    * @param _operator address to check if it has the right to manage the tokens
    * @param _tokenHolder address which holds the tokens to be managed
    * @return `true` if `_operator` is authorized for `_tokenHolder`
    */
    function isOperatorFor(address _operator, address _tokenHolder) public view returns (bool) {
        return _operator == _tokenHolder || balancesDB.getAuthorizedOperator(_operator, _tokenHolder);
        return (_operator == _tokenHolder // solium-disable-line operator-whitespace
        || balancesDB.getAuthorizedOperator(_operator, _tokenHolder)
        || (balancesDB.getDefaultOperator(_operator) && !balancesDB.getRevokedDefaultOperator(_operator, _tokenHolder)));
    }

    /**
     * @notice Helper function actually performing the sending of tokens using a backend database.
     * @param _from The address holding the tokens being sent
     * @param _to The address of the recipient
     * @param _amount The number of tokens to be sent
     * @param _data Data generated by the user to be passed to the recipient
     * @param _operatorData Data generated by the operator to be passed to the recipient
     * @param _preventLocking `true` if you want this function to throw when tokens are sent to a contract not
     *  implementing `erc777_tokenHolder`.
     *  ERC777 native Send functions MUST set this parameter to `true`, and backwards compatible ERC20 transfer
     *  functions SHOULD set this parameter to `false`.
     */
    function doSend(
        address _operator,
        address _from,
        address _to,
        uint256 _amount,
        bytes memory _data,
        bytes memory _operatorData,
        bool _preventLocking
    )
    internal
    {
        requireMultiple(_amount);

        callSender(_operator, _from, _to, _amount, _data, _operatorData);

        require(_to != address(0), "Cannot send to 0x0");          // forbid sending to 0x0 (=burning)
        // require(mBalances[_from] >= _amount); // ensure enough funds
        // (Not Required due to SafeMath throw if underflow in database and false check)

        require(balancesDB.move(_from, _to, _amount));

        callRecipient(_operator, _from, _to, _amount, _data, _operatorData, _preventLocking);

        emit Sent(_operator, _from, _to, _amount, _data, _operatorData);
        //if (mErc20compatible) { emit Transfer(_from, _to, _amount); }
    }

    /**
     * @notice Helper function actually performing the burning of tokens.
     * @param _operator The address performing the burn
     * @param _tokenHolder The address holding the tokens being burn
     * @param _amount The number of tokens to be burnt
     * @param _data Data generated by the token holder
     * @param _operatorData Data generated by the operator
     */
    function doBurn(
        address _operator,
        address _tokenHolder,
        uint256 _amount,
        bytes memory _data,
        bytes memory _operatorData
    )
    internal
    {
        revert("Burning functionality is disabled.");
    }
}
function defaultOperators() public view returns (address[] memory) {
    return balancesDB.getDefaultOperators();
}

/**
 * @notice Return the list of default operators
 * @return the list of all the default operators
 */