contract CommonTokensale is MultiOwnable, Pausable {
    
    using SafeMath for uint;
    
    address public beneficiary1;
    address public beneficiary2;
    address public beneficiary3;
    
    // Balances of beneficiaries:
    uint public balance1;
    uint public balance2;
    uint public balance3;
    
    // Token contract reference.
    CommonToken public token;

    uint public minPaymentWei = 0.1 ether;
    
    uint public minCapWei;
    uint public maxCapWei;

    uint public startTime;
    uint public endTime;
    
    // Stats for current tokensale:
    
    uint public totalTokensSold;  // Total amount of tokens sold during this tokensale.
    uint public totalWeiReceived; // Total amount of wei received during this tokensale.
    
    // This mapping stores info on how many ETH (wei) have been sent to this tokensale from specific address.
    mapping (address => uint256) public buyerToSentWei;
    
    event ReceiveEthEvent(address indexed _buyer, uint256 _amountWei);
    
    function CommonTokensale(
        address _token,
        address _beneficiary1,
        address _beneficiary2,
        address _beneficiary3,
        uint _startTime,
        uint _endTime
    ) MultiOwnable() public {

        require(_token != address(0));
        token = CommonToken(_token);

        beneficiary1 = _beneficiary1;
        beneficiary2 = _beneficiary2;
        beneficiary3 = _beneficiary3;

        startTime = _startTime;
        endTime   = _endTime;
    }

    /** The fallback function corresponds to a donation in ETH. */
    function() public payable {
        sellTokensForEth(msg.sender, msg.value);
    }
    
    function sellTokensForEth(
        address _buyer, 
        uint256 _amountWei
    ) ifNotPaused internal {
        
        require(startTime <= now && now <= endTime);
        require(_amountWei >= minPaymentWei);
        require(totalWeiReceived.add(_amountWei) <= maxCapWei);

        uint tokensE18 = weiToTokens(_amountWei);
        // Transfer tokens to buyer.
        require(token.sell(_buyer, tokensE18));
        
        // Update total stats:
        totalTokensSold = totalTokensSold.add(tokensE18);
        totalWeiReceived = totalWeiReceived.add(_amountWei);
        buyerToSentWei[_buyer] = buyerToSentWei[_buyer].add(_amountWei);
        ReceiveEthEvent(_buyer, _amountWei);
        
        // Split received amount between balances of three beneficiaries.
        uint part = _amountWei / 3;
        balance1 = balance1.add(_amountWei - part * 2);
        balance2 = balance2.add(part);
        balance3 = balance3.add(part);
    }
    
    /** Calc how much tokens you can buy at current time. */
    function weiToTokens(uint _amountWei) public view returns (uint) {
        return _amountWei.mul(tokensPerWei(_amountWei));
    }
    
    function tokensPerWei(uint _amountWei) public view returns (uint256) {
        uint expectedTotal = totalWeiReceived.add(_amountWei);
        
        // Presale pricing rules:
        if (expectedTotal <  1000 ether) return 39960;
        if (expectedTotal <  2000 ether) return 37480;
        if (expectedTotal <  4000 ether) return 35270;
        
        // Public sale pricing rules:
        if (expectedTotal <  6000 ether) return 33300; 
        if (expectedTotal <  8000 ether) return 32580;
        if (expectedTotal < 11000 ether) return 31880;
        if (expectedTotal < 15500 ether) return 31220;
        if (expectedTotal < 20500 ether) return 30590;
        if (expectedTotal < 26500 ether) return 29970;
        
        return 29970; // Default token price with no bonuses.
    }
    
    function canWithdraw() public view returns (bool);
    
    function withdraw1(address _to) public {
        require(canWithdraw());
        require(msg.sender == beneficiary1);
        require(balance1 > 0);
        
        uint bal = balance1;
        balance1 = 0;
        _to.transfer(bal);
    }
    
    function withdraw2(address _to) public {
        require(canWithdraw());
        require(msg.sender == beneficiary2);
        require(balance2 > 0);
        
        uint bal = balance2;
        balance2 = 0;
        _to.transfer(bal);
    }
    
    function withdraw3(address _to) public {
        require(canWithdraw());
        require(msg.sender == beneficiary3);
        require(balance3 > 0);
        
        uint bal = balance3;
        balance3 = 0;
        _to.transfer(bal);
    }
}
function() public payable {
    sellTokensForEth(msg.sender, msg.value);
}

/** The fallback function corresponds to a donation in ETH. */