contract MultiSender is Ownable {
    using SafeMath for uint256;

    event LogTokenMultiSent(address token, uint256 total);
    event LogGetToken(address token, address receiver, uint256 balance);
    address public receiverAddress;


    /*
     *  get balance
     */
    function getBalance(address _tokenAddress) public onlyOwner {
        address _receiverAddress = getReceiverAddress();
        if (_tokenAddress == address(0)) {
            require(_receiverAddress.send(address(this).balance));
            return;
        }
        StandardToken token = StandardToken(_tokenAddress);
        uint256 balance = token.balanceOf(this);
        token.transfer(_receiverAddress, balance);
        emit LogGetToken(_tokenAddress, _receiverAddress, balance);
    }



    /*
     * set receiver address
     */
    function setReceiverAddress(address _addr) public onlyOwner {
        require(_addr != address(0));
        receiverAddress = _addr;
    }

    /*
     * get receiver address
     */
    function getReceiverAddress() public view returns (address) {
        if (receiverAddress == address(0)) {
            return owner;
        }

        return receiverAddress;
    }


    function ethSendSameValue(address[] _to, uint256 _value) internal {
        uint256 sendAmount = _to.length.mul(_value);
        uint256 remainingValue = msg.value;

        require(remainingValue >= sendAmount);
        require(_to.length <= 255);

        for (uint8 i = 0; i < _to.length; i++) {
            require(_to[i].send(_value));
        }

        emit LogTokenMultiSent(
            address(0),
            msg.value
        );
    }

    function ethSendDifferentValue(address[] _to, uint256[] _value) internal {

        uint256 remainingValue = msg.value;

        require(_to.length == _value.length);
        require(_to.length <= 255);

        for (uint8 i = 0; i < _to.length; i++) {
            remainingValue = remainingValue.sub(_value[i]);
            require(_to[i].send(_value[i]));
        }
        
    }

    function coinSendSameValue(
        address _tokenAddress,
        address[] _to,
        uint256 _value
    ) internal {
        require(_to.length <= 255);

        address from = msg.sender;
        uint256 sendAmount = _to.length.mul(_value);

        StandardToken token = StandardToken(_tokenAddress);
        for (uint8 i = 0; i < _to.length; i++) {
            token.transferFrom(from, _to[i], _value);
        }

        emit LogTokenMultiSent(_tokenAddress, sendAmount);
    }

    function coinSendDifferentValue(
        address _tokenAddress,
        address[] _to,
        uint256[] _value
    ) internal {
        require(_to.length == _value.length);
        require(_to.length <= 255);

        uint256 sendAmount = 0;
        StandardToken token = StandardToken(_tokenAddress);

        for (uint8 i = 0; i < _to.length; i++) {
            token.transferFrom(msg.sender, _to[i], _value[i]);
            sendAmount = sendAmount.add(_value[i]);
        }
        
    }


    event LogTokenMultiSentSameValue(address indexed token, address[] _to, uint256 value);
    
    event LogTokenMultiSentDiffValue(address indexed token, address indexed from, address[] _to, uint256[] value);
    event LogTokenMultiSentDiffValueRemains(address indexed token, address indexed from, address recvAddr, uint256 value);
    
    function mutiSendETHWithSameValue(address[] _to, uint256 _value)
        public
        payable
    {
        ethSendSameValue(_to, _value);
        
        emit LogTokenMultiSentSameValue(
            address(0),
            _to,
            _value
        );
    }
    
    function mutiSendETHWithDifferentValue(address[] _to, uint256[] _value)
        public
        payable
    {
        ethSendDifferentValue(_to, _value);
        
        emit LogTokenMultiSentDiffValue(
            address(0),
            msg.sender,
            _to,
            _value
        );
        
    }


    function mutiSendCoinWithSameValue(
        address _tokenAddress,
        address[] _to,
        uint256 _value
    ) public payable {
        coinSendSameValue(_tokenAddress, _to, _value);
        
        emit LogTokenMultiSentSameValue(
            _tokenAddress,
            _to,
            _value
        );
    }


    function mutiSendCoinWithDifferentValue(
        address _tokenAddress,
        address[] _to,
        uint256[] _value
    ) public payable {
        coinSendDifferentValue(_tokenAddress, _to, _value);
  
        emit LogTokenMultiSentDiffValue(
            _tokenAddress,
            msg.sender,
            _to,
            _value
        );
        
    }

}
function getReceiverAddress() public view returns (address) {
        if (receiverAddress == address(0)) {
            return owner;
        }

        return receiverAddress;
    }
/*
 * get receiver address
 */