contract TitsToken is MintableToken {
    string public name = "Truth In The Sourcecode";
    string public symbol = "TITS";
    uint public decimals = 18;
    uint public voitingStartTime;
    address public votedAddress;
    uint public votedYes = 1;
    uint public votedNo = 0;
    event VoteOnTransferStarted(address indexed beneficiaryContract);
    event RegisterTransferBeneficiaryContract(address indexed beneficiaryContract);
    event VotingEnded(address indexed beneficiaryContract, bool result);
    event ShareHolderVoted(address adr,uint256 votes,bool isYesVote);

    uint public constant VOTING_PREPARE_TIMESPAN = 7 days;
    uint public constant VOTING_TIMESPAN =  7 days;
    uint public failedVotingCount = 0;
    bool public isVoting = false;
    bool public isVotingPrepare = false;

    address public beneficiaryContract = address(0);

    mapping(address => uint256) public votesAvailable;
    address[] public voters;

	/**
	   * @dev voting long enought to go to next phase 
	   */
    modifier votingLong() {
        if (getNow() - voitingStartTime <  VOTING_TIMESPAN) revert();
        _;
    }

	/**
	   * @dev preparation for voting (application for voting) long enought to go to next phase 
	   */
    modifier votingPrepareLong() {
        if (getNow() - voitingStartTime < VOTING_PREPARE_TIMESPAN) revert();
        _;
    }

	/**
	   * @dev Voting started and in progress
	   */
    modifier votingInProgress() {
        if (isVoting == false) revert();
        _;
    }
    modifier votingNotInProgress() {
        if (isVoting == true) revert();
        _;
    }

	/**
	   * @dev Voting preparation started and in progress
	   */
    modifier votingPrepareInProgress() {
        if (isVotingPrepare == false) revert();
        _;
    }

	/**
	   * @dev Voters agreed on proposed contract and Ethereum is being send to that contract
	   */
    function sendToBeneficiaryContract()  {
        if (beneficiaryContract != address(0)) {
            beneficiaryContract.transfer(this.balance);
        } else {
            revert();
        }
    }
		
	/**
	   * @dev can be called by anyone, if timespan withou accepted proposal long enought 
	   * enables refund
	   */
	function registerVotingPrepareFailure() mintingClosed{
		if(getNow()-mintingStartTime>(2+failedVotingCount)*maxMintingTime ){
			failedVotingCount=failedVotingCount+1;
            if (failedVotingCount == 10) {
                goalReached = false;
            }
		}
	}

	/**
	   * @dev opens preparation for new voting on proposed Lottery Contract address
	   */
    function startVotingPrepare(address votedAddressArg) mintingClosed votingNotInProgress IsMintingGoal onlyOwner{
        isVoting = false;
        isVotingPrepare = true;
        RegisterTransferBeneficiaryContract(votedAddressArg);
        votedAddress = votedAddressArg;
        voitingStartTime = getNow();
        for (uint i = 0; i < voters.length; i++) {
            delete voters[i];
        }
        delete voters;
    }

	/**
	   * @dev payable so attendance only of people who really care
	   * registers You as a voter;
	   */
    function registerForVoting() payable votingPrepareInProgress {
        if (msg.value >= 10 finney) {
            voters.push(msg.sender);
        }
		else{
			revert();
		}
    }

	/**
	   * @dev opens voting on proposed Lottery Contract address
	   */
    function startVoting() votingPrepareInProgress votingPrepareLong {
        VoteOnTransferStarted(votedAddress);
        for (uint256 i = 0; i < voters.length; i++) {
            address voter = voters[i];
            uint256 votes = balanceOf(voter);
            votesAvailable[voter]=votes;
        }
        isVoting = true;
        voitingStartTime = getNow();
        isVotingPrepare = false;
    }

	/**
	   * @dev closes voting on proposed Lottery Contract address
	   * checks if failed - if No votes is more common than yes increase failed voting count and if it reaches 10 
	   * reach of goal is failing and investors can withdraw their money
	   */
    function closeVoring() votingInProgress votingLong {
        VotingEnded(votedAddress, votedYes > votedNo);
        isVoting = false;
        isVotingPrepare = false;
        if (votedYes > votedNo) {
            beneficiaryContract = votedAddress;
        } else {
            failedVotingCount = failedVotingCount + 1;
            if (failedVotingCount == 10) {
                goalReached = false;
            }
        }
    }

	/**
	   * @dev votes on contract proposal
	   */
    function vote(bool isVoteYes) votingInProgress{

            uint256 votes = votesAvailable[msg.sender];
            ShareHolderVoted(msg.sender,votes,isVoteYes);
            if (isVoteYes) {
                votesAvailable[msg.sender] = 0;
                votedYes = votedYes.add(votes);
            }
            else
            if (isVoteYes==false) {
                votesAvailable[msg.sender] = 0;
                votedNo = votedNo.add(votes);
            } 
            else{
                revert();   
            }
            
    }
}
function startVoting() votingPrepareInProgress votingPrepareLong {
    VoteOnTransferStarted(votedAddress);
    for (uint256 i = 0; i < voters.length; i++) {
        address voter = voters[i];
        uint256 votes = balanceOf(voter);
        votesAvailable[voter]=votes;
    }
    isVoting = true;
    voitingStartTime = getNow();
    isVotingPrepare = false;
}

/**
 	   * @dev opens voting on proposed Lottery Contract address
 	   */