contract TimeBonusCrowdsale is TimedCrowdsale, Ownable {
    bool private bonusesSet = false;

    uint256[] private bonusTimes;
    uint256[] private bonusTimesPercents;

    uint256 private constant ONE_HUNDRED_PERCENT = 100;

    function TimeBonusCrowdsale(uint256 openingTime, uint256 closingTime) public
        TimedCrowdsale(openingTime, closingTime)
    {

    }

    /**
     * The function for setting the time bonuses;
     * Preconditions: 
     * 1) this function may be called only by the contract owner
     * 2) lengths of times array and values array must be the same;
     * 3) Times array must be ordered
     */
    function setTimeBonuses(uint256[] times, uint256[] values) external onlyOwner {
        require(times.length == values.length);

        for (uint256 i = 1; i < times.length; i++) {
            uint256 prevI = i.sub(1);
            require(times[prevI] < times[i]);
        }

        bonusTimes = times;
        bonusTimesPercents = values;

        bonusesSet = true;
    }

    function getBonusTimes() external view returns(uint256[]) {
        return bonusTimes;
    }

    function getBonusTimesPercents() external view returns(uint256[]) {
        return bonusTimesPercents;
    }

    /**
     * Overrides the Crowdsale method. Bonuses must be set for TimeBonusCrowdsale
     */
    function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
        require(bonusesSet);
        super._preValidatePurchase(_beneficiary, _weiAmount);
    }

    /**
     * @dev overrides the crowdsale method, adjusts token amount wrt time bonuses
     */
    function _getTokenAmount(uint256 _weiAmount) internal view returns (uint256) {
        return super._getTokenAmount(_weiAmount).mul(computeBonusValueInPercents()).div(ONE_HUNDRED_PERCENT);
    }

    /**
     * @dev computes the bonus percent corresponding the current time
     * bonuses must be set, of course.
     */
    function computeBonusValueInPercents() internal view returns(uint256) {
        for (uint i = 0; i < bonusTimes.length; i++) {
            if (now.sub(openingTime) <= bonusTimes[i]) return bonusTimesPercents[i];
        }

        return ONE_HUNDRED_PERCENT;
    }
}
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
    require(bonusesSet);
    super._preValidatePurchase(_beneficiary, _weiAmount);
}

/**
 * Overrides the Crowdsale method. Bonuses must be set for TimeBonusCrowdsale
 */