contract Remote is Ownable, IERC20 {
    using SafeMath for uint;

    IERC20 internal _remoteToken;
    address internal _remoteContractAddress;

    uint _totalSupply;

    mapping(address => uint) balances;
    mapping(address => mapping(address => uint)) allowed;

    // ------------------------------------------------------------------------
    // Total supply
    // ------------------------------------------------------------------------
    function totalSupply() public view returns (uint) {
        return _totalSupply.sub(balances[address(0)]);
    }

    // ------------------------------------------------------------------------
    // Get the token balance for account `tokenOwner`
    // ------------------------------------------------------------------------
    function balanceOf(address tokenOwner) public view returns (uint balance) {
        return balances[tokenOwner];
    }

    // ------------------------------------------------------------------------
    // Transfer the balance from token owner's account to `to` account
    // - Owner's account must have sufficient balance to transfer
    // - 0 value transfers are allowed
    // ------------------------------------------------------------------------
    function transfer(address to, uint tokens) public returns (bool success) {
        balances[msg.sender] = balances[msg.sender].sub(tokens);
        balances[to] = balances[to].add(tokens);
        emit Transfer(msg.sender, to, tokens);
        return true;
    }

    // ------------------------------------------------------------------------
    // Token owner can approve for `spender` to transferFrom(...) `tokens`
    // from the token owner's account
    //
    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
    // recommends that there are no checks for the approval double-spend attack
    // as this should be implemented in user interfaces
    // ------------------------------------------------------------------------
    function approve(address spender, uint tokens) public returns (bool success) {
        allowed[msg.sender][spender] = tokens;
        emit Approval(msg.sender, spender, tokens);
        return true;
    }

    // ------------------------------------------------------------------------
    // Transfer `tokens` from the `from` account to the `to` account
    //
    // The calling account must already have sufficient tokens approve(...)-d
    // for spending from the `from` account and
    // - From account must have sufficient balance to transfer
    // - Spender must have sufficient allowance to transfer
    // - 0 value transfers are allowed
    // ------------------------------------------------------------------------
    function transferFrom(address from, address to, uint tokens) public returns (bool success) {
        balances[from] = balances[from].sub(tokens);
        allowed[from][msg.sender] = allowed[from][msg.sender].sub(tokens);
        balances[to] = balances[to].add(tokens);
        emit Transfer(from, to, tokens);
        return true;
    }

    // ------------------------------------------------------------------------
    // Returns the amount of tokens approved by the owner that can be
    // transferred to the spender's account
    // ------------------------------------------------------------------------
    function allowance(address tokenOwner, address spender) public view returns (uint remaining) {
        return allowed[tokenOwner][spender];
    }

    /**
    @dev approveSpenderOnDex
    This is only needed if you put the funds in the Dex contract address, and then need to withdraw them
    Avoid this, by not putting funds in there that you need to get back.
    @param spender The address that will be used to withdraw from the Dex.
    @param value The amount of tokens to approve.
    @return success
     */
    function approveSpenderOnDex (address spender, uint256 value) 
        external onlyOwner returns (bool success) {
        // NOTE Approve the spender on the Dex address
        _remoteToken.approve(spender, value);     
        success = true;
    }

   /** 
    @dev remoteTransferFrom This allows the admin to withdraw tokens from the contract, using an 
    allowance that has been previously set. 
    @param from address to take the tokens from (allowance)
    @param to the recipient to give the tokens to
    @param value the amount in tokens to send
    @return bool
    */
    function remoteTransferFrom (address from, address to, uint256 value) external onlyOwner returns (bool) {
        return _remoteTransferFrom(from, to, value);
    }

    /**
    @dev setRemoteContractAddress
    @param remoteContractAddress The remote contract's address
    @return success
     */
    function setRemoteContractAddress (address remoteContractAddress)
        external onlyOwner returns (bool success) {
        _remoteContractAddress = remoteContractAddress;        
        _remoteToken = IERC20(_remoteContractAddress);
        success = true;
    }

    function remoteBalanceOf(address owner) external view returns (uint256) {
        return _remoteToken.balanceOf(owner);
    }

    function remoteTotalSupply() external view returns (uint256) {
        return _remoteToken.totalSupply();
    }

    /** */
    function remoteAllowance (address owner, address spender) external view returns (uint256) {
        return _remoteToken.allowance(owner, spender);
    }

    /**
    @dev remoteBalanceOfDex Return tokens from the balance of the Dex contract.
    @return balance
     */
    function remoteBalanceOfDex () external view onlyOwner 
        returns(uint256 balance) {
        balance = _remoteToken.balanceOf(address(this));
    }

    /**
    @dev remoteAllowanceOnMyAddress Check contracts allowance on the users address.
    @return allowance
     */
    function remoteAllowanceOnMyAddress () public view
        returns(uint256 myRemoteAllowance) {
        myRemoteAllowance = _remoteToken.allowance(msg.sender, address(this));
    } 

    /** 
    @dev _remoteTransferFrom This allows contract to withdraw tokens from an address, using an 
    allowance that has been previously set. 
    @param from address to take the tokens from (allowance)
    @param to the recipient to give the tokens to
    @param value the amount in tokens to send
    @return bool
    */
    function _remoteTransferFrom (address from, address to, uint256 value) internal returns (bool) {
        return _remoteToken.transferFrom(from, to, value);
    }

}
function remoteAllowance (address owner, address spender) external view returns (uint256) {
    return _remoteToken.allowance(owner, spender);
}

/** */