contract MintableToken is StandardToken, Ownable {
    event Mint(address indexed to, uint256 amount);
    event MintFinished();
    event MintStarted();
    event RefundRequest(uint256 sum,address adr,uint256 balance);
    event CoinBuy(uint256 sum,address adr);
    

    bool public mintingFinished = true;
    bool public goalReached = false;
    uint public mintingStartTime = 0;
    uint public maxMintingTime = 30 days;
    uint public mintingGoal = 500 ether;

    address public titsTokenAuthor = 0x189891d02445D87e70d515fD2159416f023B0087;

	/**
	   * @dev Fell fre to donate Author if You like what is presented here
	   */
    function donateAuthor() payable {
        titsTokenAuthor.transfer(msg.value);
    }

    bool public alreadyMintedOnce = false;

    modifier mintingClosed() {
        if (mintingFinished == false || alreadyMintedOnce == false) revert();
        _;
    }
    
    modifier IsMintingGoal() {
        if (mintingFinished == false || alreadyMintedOnce == false || goalReached == false ) revert();
        _;
    }

    modifier notMintedYet() {
        if (alreadyMintedOnce == true) revert();
        _;
    }

    function getNow() public returns(uint256){
        return now;
    }
    
	/**
	   * @dev Premium for buying TITS at the begining of ICO 
	   * @return bool True if no errors
	   */
    function fastBuyBonus() private returns(uint) {
        uint period = getNow() - mintingStartTime;
        if (period < 1 days) {
            return 3500;
        }
        if (period < 2 days) {
            return 3200;
        }
        if (period < 3 days) {
            return 3000;
        }
        if (period < 7 days) {
            return 2600;
        }
        if (period < 10 days) {
            return 2400;
        }
        if (period < 12 days) {
            return 2200;
        }
        if (period < 14 days) {
            return 2000;
        }
        if (period < 17 days) {
            return 1800;
        }
        if (period < 19 days) {
            return 1600;
        }
        if (period < 21 days) {
            return 1400;
        }
        if (period < 23 days) {
            return 1200;
        }
        return 1000;
    }

	/**
	   * @dev Allows to buy shares
	   * @return bool True if no errors
	   */
    function buy() payable returns(bool) {
        if (mintingFinished) {
            revert();
        }

        uint _amount = 0;
        _amount = msg.value * fastBuyBonus();
        totalSupply = totalSupply.add(_amount);
        CoinBuy(_amount,msg.sender);
        balances[msg.sender] = balances[msg.sender].add(_amount);
        balances[owner] = balances[owner].add(_amount / 85 * 15); //15% shares of owner
        totalSupply = totalSupply.add(_amount / 85 * 15);
        return true;
    }

	/**
	   * @dev Opens ICO (only owner)
	   * @return bool True if no errors
	   */
    function startMinting() onlyOwner notMintedYet returns(bool) {
        mintingStartTime = getNow();
        alreadyMintedOnce = true;
        mintingFinished = false;
        MintStarted();
        return true;
    }

	/**
	   * @dev Closes ICO - anyone can invoke if invoked to soon, takes no actions
	   * @return bool True if no errors
	   */
    function finishMinting() returns(bool) {
        if (mintingFinished == false) {
            if (getNow() - mintingStartTime > maxMintingTime) {
                mintingFinished = true;
                MintFinished();
                goalReached = (this.balance > mintingGoal);
                return true;
            }
        }
        revert();
    }

	/**
	   * @dev Function refunds contributors if ICO was unsuccesful 
	   * @return bool True if conditions for refund are met false otherwise.
	   */
    function refund() returns(bool) {
        if (mintingFinished == true && goalReached == false && alreadyMintedOnce == true) {
            uint256 valueOfInvestment =  this.balance.mul(balances[msg.sender]).div(totalSupply);
            totalSupply.sub(balances[msg.sender]);
            RefundRequest(valueOfInvestment,msg.sender,balances[msg.sender]);
            balances[msg.sender] = 0;
            msg.sender.transfer(valueOfInvestment);
			return true;
        }
        revert();
    }
 
}
function startMinting() onlyOwner notMintedYet returns(bool) {
    mintingStartTime = getNow();
    alreadyMintedOnce = true;
    mintingFinished = false;
    MintStarted();
    return true;
}

/**
 	   * @dev Opens ICO (only owner)
 	   * @return bool True if no errors
 	   */