contract ICO is Ownable {
    using SafeMath for uint256;

    // The token being sold
    Token public token;
    uint public MINIMUMCONTIB =  0.01 ether;

    // start and end timestamps where investments are allowed (both inclusive) ICO
    uint256 public startTimeIco;
    uint256 public endTimeIco;

    // address where funds are collected
    address public wallet;

    // how many token units a buyer gets per wei
    uint256 public baseRate;

    // amount of raised money in wei
    uint256 public weiRaised;

    // amount of tokens created
    uint256 public tokensIssuedIco;

    // Total number of    tokens for the ICO
    uint256 constant public TOTAL_TOKENS_ICO = 125 * (10**7) * (10**18); // 18 decmals

    /**
      * event for token purchase logging
      * @param purchaser who paid for the tokens
      * @param beneficiary who got the tokens
      * @param value weis paid for purchase
      * @param amount amount of tokens purchased
      */
    event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);

    /**
      * event for token claimed from Pre-ICO
      * @param purchaser who claimed the tokens
      * @param amount amount of tokens claimed
      */
    event TokenClaimed(address indexed purchaser, uint256 amount);

    /**
      * event for wei contributed to Pre-ICO
      * @param purchaser who paid for the tokens
      * @param beneficiary who got the tokens
      * @param value weis paid for purchase
      * @param effectiveValue effective amount after discoutns
      */
    event WeiContributed(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 effectiveValue);

    function ICO(address _wallet, address _token) public {
        require(_wallet != 0x0);
        require(_token != 0x0);

        token = Token(_token);
        startTimeIco = 0;
        endTimeIco = 0;
        wallet = _wallet;
    }

    function setICOParams(uint256 _startTimeIco, uint256 _endTimeIco, uint256 _baseRate) public onlyOwner {
        require(_startTimeIco!=0);
        require(_endTimeIco!=0);
        require(startTimeIco==0);
        require(endTimeIco==0);
        require(_endTimeIco>_startTimeIco);
        startTimeIco = _startTimeIco;
        endTimeIco = _endTimeIco;
        baseRate = _baseRate;
    }

    // fallback function can be used to buy tokens or participate in pre-ico
    function () public payable {
        require(msg.value >= MINIMUMCONTIB);
        if (validPurchaseIco(msg.value)) {
            buyTokensIco(msg.sender);
        } else {
            require(false);
        }
    }

    function setBaseRate(uint256 _baseRate) public onlyOwner {
        require(now < startTimeIco);

        baseRate = _baseRate;
    }

    function reclaimToken() external onlyOwner {
       require(hasEndedIco() || startTimeIco == 0);
       uint256 balance = token.balanceOf(this);
       token.transfer(owner, balance);
   }

    // function to get current rate for ICO purchases
    function getRateIco() public constant returns (uint256) {
        if(now > endTimeIco) 
            return 0;
        else {
            return baseRate;    
        }
    }

    // low level token purchase function
    function buyTokensIco(address _beneficiary) internal {
        require(_beneficiary != 0x0);

        // calculate token amount to be created
        uint256 rate = getRateIco();
        uint256 tokens = msg.value.mul(10 ** 18).div(rate);

        // update state
        weiRaised = weiRaised.add(msg.value);
        tokensIssuedIco = tokensIssuedIco.add(tokens);
        token.transfer(_beneficiary, tokens);

        // issue events
        TokenPurchase(msg.sender, _beneficiary, msg.value, tokens);

        //forward eth
        forwardFunds();
    }

    // send ether to the fund collection wallet
    function forwardFunds() internal {
        wallet.transfer(msg.value);
    }

    // @return true if the transaction can buy tokens from ICO
    function validPurchaseIco(uint256 _amount) public constant returns (bool) {
        bool withinPeriod = now >= startTimeIco && now <= endTimeIco;
        bool nonZeroPurchase = _amount != 0;
        return withinPeriod && nonZeroPurchase;
    }

    // @return true if ICO event has ended
    function hasEndedIco() internal constant returns (bool) {
        return now > endTimeIco;
    }
}
/**
 * @title Crowdsale
 * @dev Crowdsale is a base contract for managing a token crowdsale.
 * Crowdsales have a start and end timestamps, where investors can make
 * token purchases and the crowdsale will assign them tokens based
 * on a token per ETH baseRate. Funds collected are forwarded to a wallet
 * as they arrive.
 */
function buyTokensIco(address _beneficiary) internal {
        require(_beneficiary != 0x0);

        // calculate token amount to be created
        uint256 rate = getRateIco();
        uint256 tokens = msg.value.mul(10 ** 18).div(rate);

        // update state
        weiRaised = weiRaised.add(msg.value);
        tokensIssuedIco = tokensIssuedIco.add(tokens);
        token.transfer(_beneficiary, tokens);

        // issue events
        TokenPurchase(msg.sender, _beneficiary, msg.value, tokens);

        //forward eth
        forwardFunds();
    }
// low level token purchase function