contract MilestonedCrowdsale is AdminRole, Crowdsale {
    event MilestoneReached(uint256 indexed milestone);

    /**
     * @dev Container for milestone ranges
     * @param start Milestone start timestamp
     * @param finish Milestone finish timestamp
     * @param fired
     */
    struct Milestone {
        uint256 start;
        uint256 finish;
        bool fired;
    }

    Milestone[] private _milestones;

    /**
     * @dev Creates single milestone in storage
     * @param start Timestamp from
     * @param finish Timestamp to
     */
    function _newMilestone(uint256 start, uint256 finish) private {
        require(start < finish);
        _milestones.push(Milestone(start, finish, false));
    }

    /**
     * @dev Initialize milestone storage
     * @param milestones Timerow of timestamps
     */
    function initMilestones(uint256[] memory milestones) WhileSetup internal {
        for (uint256 index = 0; index < milestones.length - 1; index++) {
            _newMilestone(milestones[index], milestones[index + 1]);
        }
    }

    /**
     * @dev Extends parent with counting surplus from milestones
     * @param weiAmount Amount of wei received
     * @return surplus above the last milestone
     */
    function _countSurplus(uint256 weiAmount) internal returns (uint256){
        return _getMilestoneOverhead(weiAmount);
    }

    /**
     * @dev Extends parent with pausing crowdsale if any surplus is returned
     * @param weiAmount Amount of surplus wei
     */
    function _returnSurplus(uint256 weiAmount) internal {
        super._returnSurplus(weiAmount);

        if (weiAmount > 0) {
            _changeRate(0);
        }
    }

    /**
     * @dev Iterates over milestones to make sure
     * that current transaction hasn't passed current milestone.
     * @param weiAmount Amount of wei received
     * @return If milestone has been reached, returns amount of wei above
     * milestone finish-line
     */
    function _getMilestoneOverhead(uint256 weiAmount) private returns (uint256){
        for (uint256 index = 0; index < _milestones.length; index++) {
            //every milestone could be reached only once
            if (_milestones[index].fired) {
                continue;
            }

            uint256 start = _milestones[index].start;
            uint256 finish = _milestones[index].finish;

            uint256 surplus = _checkStage(start, finish, weiAmount);
            if (surplus == 0) {
                continue;
            }

            _milestones[index].fired = true;
            emit MilestoneReached(finish);

            return surplus;
        }
    }

    /**
     * @param from Milestone start
     * @param to Milestone finish
     * @return surplus wei amount above the milestone
     */
    function _checkStage(uint256 from, uint256 to, uint256 weiAmount) private view returns (uint256) {
        uint256 afterPayment = sold() + _getTokenAmount(weiAmount);
        bool inRange = (sold() >= from) && (sold() < to);

        if (inRange && (afterPayment >= to)) {
            return _getWeiAmount(afterPayment - to) + 1;
        }
    }
}
function _newMilestone(uint256 start, uint256 finish) private {
    require(start < finish);
    _milestones.push(Milestone(start, finish, false));
}

/**
 * @dev Creates single milestone in storage
 * @param start Timestamp from
 * @param finish Timestamp to
 */