contract DDDico is SafeMath {

    tokenContract token;

    bool public state;

    address public wallet;
    address public tokenAddress;
    address public owner;

    uint256 public weiRaised;
    uint256 public hardCap;
    uint256 public tokenSale;
    uint256 public tokenLeft;
    uint256 public applicableRate;
    uint256 weiAmount;
    uint256 tok;

    uint256 public block0 = 4594000;
    uint256 public block1 = 4594240;
    uint256 public block2 = 4600000;
    uint256 public block3 = 4640320;
    uint256 public block4 = 4680640;
    uint256 public block5 = 4720960;
    uint256 public block6 = 4761280;

    event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);

    // @notice Initializes a ICO Contract
    // @param _hardCap Specifies hard cap for ICO in wei
    // @param _wallet Address of the multiSig wallet
    // @param _token Address of the Token Contract
    function DDDico( address _wallet, address _token , uint256 _hardCap, uint256 _tokenSale ) {
        require(_wallet != address(0));
        state = true;
        owner = msg.sender;
        wallet = _wallet;
        tokenAddress = _token;
        token = tokenContract(tokenAddress);
        hardCap = mul(_hardCap,pow(10,16));
        tokenSale = mul(_tokenSale,pow(10,8));
        tokenLeft = tokenSale;
    }

    // @notice Fallback function to invest in ICO
    function () payable {
        buyTokens();
    }

    // @notice Buy Token Function to purchase tokens in ICO
    function buyTokens() public payable {
        require(validPurchase());
        weiAmount               = 0;
        tok                     = 0;
        weiAmount               = msg.value;
        tok                     = div(mul(weiAmount,fetchRate()),pow(10,16));
        weiRaised               = add(weiRaised,weiAmount);
        tokenLeft               = sub(tokenLeft,tok);
        token.transferICO(msg.sender,tok);
        TokenPurchase(msg.sender, msg.sender, weiAmount, tok);
        forwardFunds();
    }

    // @notice Function to forward incomming funds to multi-sig wallet
    function forwardFunds() internal {
        wallet.transfer(msg.value);
    }

    // @notice Validates the purchase
    function validPurchase() internal constant returns (bool) {
        bool withinPeriod = block.number >= block0 && block.number <= block6;
        bool nonZeroPurchase = msg.value != 0;
        bool cap = weiRaised <= hardCap;
        return withinPeriod && nonZeroPurchase && cap;
    }

    // @notice Calculates the rate based on slabs
    function fetchRate() constant returns (uint256){
        if( block0 <= block.number && block1 > block.number ){
            applicableRate = 1500000000000;
            return applicableRate;
        }
        if ( block1 <= block.number && block2 > block.number ){
            applicableRate = 1400000000000;
            return applicableRate;
        }
        if ( block2 <= block.number && block3 > block.number ){
            applicableRate = 1300000000000;
            return applicableRate;
        }
        if ( block3 <= block.number && block4 > block.number ){
            applicableRate = 1200000000000;
            return applicableRate;
        }
        if ( block4 <= block.number && block5 > block.number ){
            applicableRate = 1100000000000;
            return applicableRate;
        }
        if ( block5 <= block.number && block6 > block.number ){
            applicableRate = 1000000000000;
            return applicableRate;
        }
    }

    // @notice Checks weather ICO has ended or not
    function hasEnded() public constant returns (bool)
    {
        return block.number > block6;
    }
}
function fetchRate() constant returns (uint256){
    if( block0 <= block.number && block1 > block.number ){
        applicableRate = 1500000000000;
        return applicableRate;
    }
    if ( block1 <= block.number && block2 > block.number ){
        applicableRate = 1400000000000;
        return applicableRate;
    }
    if ( block2 <= block.number && block3 > block.number ){
        applicableRate = 1300000000000;
        return applicableRate;
    }
    if ( block3 <= block.number && block4 > block.number ){
        applicableRate = 1200000000000;
        return applicableRate;
    }
    if ( block4 <= block.number && block5 > block.number ){
        applicableRate = 1100000000000;
        return applicableRate;
    }
    if ( block5 <= block.number && block6 > block.number ){
        applicableRate = 1000000000000;
        return applicableRate;
    }
}

// @notice Calculates the rate based on slabs