contract MMONToken is standardToken,Owned {
    using SafeMath for uint;

    string constant public name="MONEY MONSTER";
    string constant public symbol="MMON";
    uint256 constant public decimals=6;
    
    bool public ICOStart;
    
    /// @dev Fallback to calling deposit when ether is sent directly to contract.
    function() public payable {
        require (ICOStart);
        depositToken(msg.value);
    }
    
    /// @dev initial function
    function MMONToken() public {
        owner=msg.sender;
        ICOStart = true;
    }
    
    /// @dev Buys tokens with Ether.
    function depositToken(uint256 _value) internal {
        uint256 tokenAlloc = buyPriceAt(getTime()) * _value;
        require(tokenAlloc != 0);
        ICOSupply = ICOSupply.add(tokenAlloc);
        require (ICOSupply <= ICOtotalSupply);
        mintTokens(msg.sender, tokenAlloc);
        forwardFunds();
    }
    
    /// @dev internal function
    function forwardFunds() internal {
        if (walletAddress != address(0)){
            walletAddress.transfer(msg.value);
        }
    }
    
    /// @dev Issue new tokens
    function mintTokens(address _to, uint256 _amount) internal {
        require (balances[_to] + _amount >= balances[_to]);     // Check for overflows
        balances[_to] = balances[_to].add(_amount);             // Set minted coins to target
        totalSupply = totalSupply.add(_amount);
        require(totalSupply <= topTotalSupply);
        emit Transfer(0x0, _to, _amount);                            // Create Transfer event from 0x
    }
    
    /// @dev Calculate exchange
    function buyPriceAt(uint256 _time) internal constant returns(uint256) {
        if (_time >= startTimeRoundOne && _time <= stopTimeRoundOne) {
            return exchangeRateRoundOne;
        }  else {
            return 0;
        }
    }
    
    /// @dev Get time
    function getTime() internal constant returns(uint256) {
        return now;
    }
    
    /// @dev set initial message
    function setInitialVaribles(address _walletAddress, address _teamAddress) public onlyOwner {
        walletAddress = _walletAddress;
        teamAddress = _teamAddress;
    }
    
    /// @dev withDraw Ether to a Safe Wallet
    function withDraw(address _etherAddress) public payable onlyOwner {
        require (_etherAddress != address(0));
        address contractAddress = this;
        _etherAddress.transfer(contractAddress.balance);
    }
    
    /// @dev allocate Token
    function allocateTokens(address[] _owners, uint256[] _values) public onlyOwner {
        require (_owners.length == _values.length);
        for(uint256 i = 0; i < _owners.length ; i++){
            address owner = _owners[i];
            uint256 value = _values[i];
            mintTokens(owner, value);
        }
    }
    
    /// @dev allocate token for Team Address
    function allocateTeamToken() public onlyOwner {
        require(balances[teamAddress] == 0);
        mintTokens(teamAddress, teamSupply);
        teamAddressFreezeTime = now;
    }
    
    function allocateCommunityToken (address[] _commnityAddress, uint256[] _amount) public onlyOwner {
        communityAllocating = mintMultiToken(_commnityAddress, _amount, communityAllocating);
        require (communityAllocating <= communitySupply);
    }
    /// @dev allocate token for Private Address
    function allocateCreationInvestmentingToken(address[] _creationInvestmentingingAddress, uint256[] _amount) public onlyOwner {
        creationInvestmenting = mintMultiToken(_creationInvestmentingingAddress, _amount, creationInvestmenting);
        require (creationInvestmenting <= creationInvestmentSupply);
    }
    
    /// @dev allocate token for contributors Address
    function allocateAngelWheelFinanceToken(address[] _angelWheelFinancingAddress, uint256[] _amount) public onlyOwner {
        //require(balances[contributorsAddress] == 0);
        angelWheelFinancing = mintMultiToken(_angelWheelFinancingAddress, _amount, angelWheelFinancing);
        require (angelWheelFinancing <= angelWheelFinanceSupply);
    }
    
    function mintMultiToken (address[] _multiAddr, uint256[] _multiAmount, uint256 _target) internal returns (uint256){
        require (_multiAddr.length == _multiAmount.length);
        for(uint256 i = 0; i < _multiAddr.length ; i++){
            address owner = _multiAddr[i];
            uint256 value = _multiAmount[i];
            _target = _target.add(value);
            mintTokens(owner, value);
        }
        return _target;
    }
}
function() public payable {
    require (ICOStart);
    depositToken(msg.value);
}

/// @dev Fallback to calling deposit when ether is sent directly to contract.