contract ICO is AdvancedToken {
    using SafeMath for uint256;

    enum State { Presale, waitingForICO, ICO, Active }
    State public contract_state = State.Presale;

    uint256 private startTime;
    uint256 private presaleMaxSupply;
    uint256 private marketMaxSupply;

    event NewState(State state);

    // Purchasing tokens is only allowed for Presale and ICO contract states
    modifier crowdsaleState {
        require(contract_state == State.Presale || contract_state == State.ICO);
        _;
    }

    // Call functions transfer transferFrom and approve, is only allowed with Active state of the contract
    modifier activeState {
        require(contract_state == State.Active);
        _;
    }

    // The initialization values when the contract has been mined to the blockchain
    function ICO() internal {
        startTime = 1528205440; // pomeriggio
        presaleMaxSupply = 0 * 1 ether;
        marketMaxSupply = 450000000 * 1 ether;
    }

    // The function of purchasing tokens
    function () private payable crowdsaleState {
        require(msg.value >= 0.01 ether);
        require(now >= startTime);
        uint256 currentMaxSupply;
        uint256 tokensPerEther = 5000;
        uint256 _tokens = tokensPerEther * msg.value;
        uint256 bonus = 0;

        // PRE-SALE calculation of bonuses
        // NOTE: PRE-SALE will be not used for TESTERIUM
        if (contract_state == State.Presale) {
            // PRE-SALE supply limit
            currentMaxSupply = presaleMaxSupply;
            // For the tests replace days to minutes
            if (now <= startTime + 1 days) {
                bonus = 25;
            } else if (now <= startTime + 2 days) {
                bonus = 20;
            }
        // ICO supply limit
        } else {
            currentMaxSupply = marketMaxSupply;
        }

        _tokens += _tokens * bonus / 100;
        uint256 restTokens = currentMaxSupply - totalSupply;
        // If supplied tokens more that the rest of the tokens, will refund the excess ether
        if (_tokens > restTokens) {
            uint256 bonusTokens = restTokens - restTokens / (100 + bonus) * 100;
            // The wei that the investor will spend for this purchase
            uint256 spentWei = (restTokens - bonusTokens) / tokensPerEther;
            // Verify that not return more than the incoming ether
            assert(spentWei < msg.value);
            // Will refund extra ether
            msg.sender.transfer(msg.value - spentWei);
            _tokens = restTokens;
        }
        mintTokens(msg.sender, _tokens);
    }

    // Finish the PRE-SALE period, is required the Presale state of the contract
    function finishPresale() public onlyOwner returns (bool success) {
        require(contract_state == State.Presale);
        contract_state = State.waitingForICO;
        NewState(contract_state);
        return true;
    }

    // Start the ICO period, is required the waitingForICO state of the contract
    function startICO() public onlyOwner returns (bool success) {
        require(contract_state == State.waitingForICO);
        contract_state = State.ICO;
        NewState(contract_state);
        return true;
    }

    // Our tokens
    function finishICO() public onlyOwner returns (bool success) {
        require(contract_state == State.ICO);
        mintTokens(owner, 50000000000000000000000000);
        contract_state = State.Active;
        NewState(contract_state);
        return true;
    }
}
function finishPresale() public onlyOwner returns (bool success) {
    require(contract_state == State.Presale);
    contract_state = State.waitingForICO;
    NewState(contract_state);
    return true;
}

// Finish the PRE-SALE period, is required the Presale state of the contract