contract TutellusCrowdsale is CappedCrowdsale, FinalizableCrowdsale, Pausable {
    event ConditionsAdded(address indexed beneficiary, uint256 rate);
    
    mapping(address => uint256) public conditions;

    uint256 salePercent = 60;   // Percent of TUTs for sale
    uint256 poolPercent = 30;   // Percent of TUTs for pool
    uint256 teamPercent = 10;   // Percent of TUTs for team

    uint256 vestingLimit; // 400 ether;
    uint256 specialLimit; // 200 ether;

    uint256 minPreICO; // 5 ether;
    uint256 minICO; // 0.05 ether;

    uint256 unitTimeSecs; //86400 secs;

    address teamTimelock; //Team TokenTimelock.

    TutellusVault vault;
    TutellusLockerVault locker;

    function TutellusCrowdsale(
        uint256 _startTime,
        uint256 _endTime,
        uint256 _cap,
        address _wallet,
        address _teamTimelock,
        address _tutellusVault,
        address _lockerVault,
        uint256 _vestingLimit,
        uint256 _specialLimit,
        uint256 _minPreICO,
        uint256 _minICO,
        uint256 _unitTimeSecs
    )
        CappedCrowdsale(_cap)
        Crowdsale(_startTime, _endTime, 1000, _wallet)
    {
        require(_teamTimelock != address(0));
        require(_tutellusVault != address(0));
        require(_vestingLimit > _specialLimit);
        require(_minPreICO > _minICO);
        require(_unitTimeSecs > 0);

        teamTimelock = _teamTimelock;
        vault = TutellusVault(_tutellusVault);
        token = MintableToken(vault.token());

        locker = TutellusLockerVault(_lockerVault);

        vestingLimit = _vestingLimit;
        specialLimit = _specialLimit;
        minPreICO = _minPreICO;
        minICO = _minICO;
        unitTimeSecs = _unitTimeSecs;
    }

    function addSpecialRateConditions(address _address, uint256 _rate) public onlyOwner {
        require(_address != address(0));
        require(_rate > 0);

        conditions[_address] = _rate;
        ConditionsAdded(_address, _rate);
    }

    // Returns TUTs rate per 1 ETH depending on current time
    function getRateByTime() public constant returns (uint256) {
        uint256 timeNow = now;
        if (timeNow > (startTime + 94 * unitTimeSecs)) {
            return 1500;
        } else if (timeNow > (startTime + 87 * unitTimeSecs)) {
            return 1575; // + 5%
        } else if (timeNow > (startTime + 80 * unitTimeSecs)) {
            return 1650; // + 10%
        } else if (timeNow > (startTime + 73 * unitTimeSecs)) {
            return 1800; // + 20%
        } else if (timeNow > (startTime + 56 * unitTimeSecs)) {
            return 2025; // + 35%
        } else if (timeNow > (startTime + 42 * unitTimeSecs)) {
            return 2100; // + 40%
        } else if (timeNow > (startTime + 28 * unitTimeSecs)) {
            return 2175; // + 45%
        } else {
            return 2250; // + 50%
        }
    }

    function buyTokens(address beneficiary) whenNotPaused public payable {
        require(beneficiary != address(0));
        require(msg.value >= minICO && msg.value <= vestingLimit);
        require(validPurchase());

        uint256 senderRate;

        if (conditions[beneficiary] != 0) {
            require(msg.value >= specialLimit);
            senderRate = conditions[beneficiary];
        } else {
            senderRate = getRateByTime();
            if (senderRate > 1800) {
                require(msg.value >= minPreICO);
            }
        }

        uint256 weiAmount = msg.value;
        // calculate token amount to be created
        uint256 tokens = weiAmount.mul(senderRate);
        // update state
        weiRaised = weiRaised.add(weiAmount);

        locker.deposit(beneficiary, tokens);
        vault.mint(locker, tokens);
        TokenPurchase(msg.sender, beneficiary, weiAmount, tokens);

        forwardFunds();
    }

    // Calculate the Tokens in percent over de tokens generated
    function poolTokensByPercent(uint256 _percent) internal returns(uint256) {
        return token.totalSupply().mul(_percent).div(salePercent);
    }

    // Method to mint the team and pool tokens
    function finalization() internal {
        uint256 tokensPool = poolTokensByPercent(poolPercent);
        uint256 tokensTeam = poolTokensByPercent(teamPercent);

        vault.mint(wallet, tokensPool);
        vault.mint(teamTimelock, tokensTeam);
    }

    function createTokenContract() internal returns (MintableToken) {}
}
/**
 * @title TutellusCrowdsale
 *
 * @dev Crowdsale for the Tutellus.io ICO.
 *
 * Upon finalization the pool and the team's wallet are mined. It must be
 * finalized once all the backers (including the vesting ones) have made
 * their contributions.
 */
function finalization() internal {
    uint256 tokensPool = poolTokensByPercent(poolPercent);
    uint256 tokensTeam = poolTokensByPercent(teamPercent);

    vault.mint(wallet, tokensPool);
    vault.mint(teamTimelock, tokensTeam);
}

// Method to mint the team and pool tokens