contract Moozicore is Crowdsale {

    uint256 constant CAP =  1000000000000000000000000000;
    uint256 constant CAP_PRE_SALE = 166000000000000000000000000;
    uint256 constant CAP_ICO_SALE = 498000000000000000000000000;

    uint256 constant RATE_PRE_SALE_WEEK1 = 100000;
    uint256 constant RATE_PRE_SALE_WEEK2 = 95000;
    uint256 constant RATE_PRE_SALE_WEEK3 = 90000;
    uint256 constant RATE_PRE_SALE_WEEK4 = 85000;

    uint256 constant RATE_ICO_SALE_WEEK1 = 80000;
    uint256 constant RATE_ICO_SALE_WEEK2 = 75000;
    uint256 constant RATE_ICO_SALE_WEEK3 = 72500;
    uint256 constant RATE_ICO_SALE_WEEK4 = 70000;

    uint256 public startTime;
    uint256 public endTime;

    uint256 public totalSupplyIco;

    function Moozicore (
        uint256 _startTime,
        uint256 _endTime,
        uint256 _rate,
        address _wallet
    ) public 
        Crowdsale(_startTime, _endTime, _rate, _wallet)
    {
        startTime = _startTime;
        endTime = _endTime;
    }

    function createTokenContract() internal returns (MintableToken) {
        return new MziToken();
    }

    // overriding Crowdsale#validPurchase
    function validPurchase() internal constant returns (bool) {

        if (msg.value < 50000000000000000) {
            return false;
        }

        if (token.totalSupply().add(msg.value.mul(getRate())) >= CAP) {
            return false;
        }
        
        if (now >= 1517266799 && now < 1533110400) {
            return false;
        }

        if (now <= 1517266799) {
            if (token.totalSupply().add(msg.value.mul(getRate())) >= CAP_PRE_SALE) {
                return false;
            }
        }

        if (now >= 1533110400) {
            if (totalSupplyIco.add(msg.value.mul(getRate())) >= CAP_ICO_SALE) {
                return false;
            }
        }

        return super.validPurchase();
    }

     function buyTokens(address beneficiary) payable public {
        require(beneficiary != address(0));
        require(validPurchase());

        uint256 weiAmount = msg.value;
        uint256 tokens = weiAmount.mul(getRate());
        weiRaised = weiRaised.add(weiAmount);

        token.mint(beneficiary, tokens);
        TokenPurchase(msg.sender, beneficiary, weiAmount, tokens);

        if (now >= 1533110400) {
            totalSupplyIco = totalSupplyIco.add(tokens);
        }

        forwardFunds();
    }

    function getRate() public constant returns (uint256) {
        uint256 currentRate = RATE_ICO_SALE_WEEK4;

        if (now <= 1515452399) {
            currentRate = RATE_PRE_SALE_WEEK1;
        } else if (now <= 1516057199) {
            currentRate = RATE_PRE_SALE_WEEK2;
        } else if (now <= 1516661999) {
            currentRate = RATE_PRE_SALE_WEEK3;
        } else if (now <= 1517266799) {
            currentRate = RATE_PRE_SALE_WEEK4;
        } else if (now <= 1533679199) {
            currentRate = RATE_ICO_SALE_WEEK1;
        } else if (now <= 1534283999) {
            currentRate = RATE_ICO_SALE_WEEK2;
        } else if (now <= 1534888799) {
            currentRate = RATE_ICO_SALE_WEEK3;
        } else if (now <= 1535493599) {
            currentRate = RATE_ICO_SALE_WEEK4;
        }

        return currentRate;
    }

    function mintTokens(address walletToMint, uint256 t) payable public {
        require(msg.sender == wallet);
        require(token.totalSupply().add(t) < CAP);
        
        if (now <= 1517266799) {
            require(token.totalSupply().add(t) < CAP_PRE_SALE);
        }

        if (now > 1517266799) {
            require(totalSupplyIco.add(t) < CAP_ICO_SALE);
            totalSupplyIco = totalSupplyIco.add(t);
        }

        token.mint(walletToMint, t);
    }
}
function validPurchase() internal constant returns (bool) {

    if (msg.value < 50000000000000000) {
        return false;
    }

    if (token.totalSupply().add(msg.value.mul(getRate())) >= CAP) {
        return false;
    }
        
    if (now >= 1517266799 && now < 1533110400) {
        return false;
    }

    if (now <= 1517266799) {
        if (token.totalSupply().add(msg.value.mul(getRate())) >= CAP_PRE_SALE) {
            return false;
        }
    }

    if (now >= 1533110400) {
        if (totalSupplyIco.add(msg.value.mul(getRate())) >= CAP_ICO_SALE) {
            return false;
        }
    }

    return super.validPurchase();
}

// overriding Crowdsale#validPurchase