// File: MANAry_mainnet_V1.0.0.sol



pragma solidity 0.5.4;

import "./SafeMath.sol";
import "./Owned.sol";


contract MANAToken {
  function transferFrom(address _from, address _to, uint256 _value) public returns (bool);
  function transfer(address _to, uint256 _value) public returns (bool);
  function balanceOf(address owner) public view returns (uint256);
}

contract MANAry is Owned{
    using SafeMath for uint256;

    MANAToken token;
   
    constructor() public {
    token = MANAToken(0x0F5D2fB29fb7d3CFeE444a200298f468908cC942);
    }
    
    struct tickets {address _owner; uint numOfTickets;}
    mapping (address => mapping (uint => tickets)) ownerOfTickets;
    
    address [] playerAddress;
    address [] entries;
    address [] winner;
    
    uint public players=0;
    uint public potTotal = 0;
    uint public roundNumber = 0;
    uint public numOfTicketsSold = 0;
    uint public cap = 100;
    
    uint unlockTime = now + 7 days + 30 minutes;
    
    function buyTickets(uint amount) public payable onlyWhenTimeIsLeft{
        require(amount > 0);
        
        uint ticket = 0;
        ticket = amount.div(100000000000000000000);
        
        require((ownerOfTickets[msg.sender][roundNumber].numOfTickets+ticket)<=15);
        require((numOfTicketsSold+ticket) <= cap);
        if((numOfTicketsSold+ticket) >= cap){
            unlockTime=0;
        }
        
        if (ticket > 0){
        require(token.transferFrom(msg.sender, address(this), amount));
        players++;
        playerAddress.push(msg.sender);
        potTotal = token.balanceOf(address(this));
        
        if (ownerOfTickets[msg.sender][roundNumber].numOfTickets == 0)
        {
        ownerOfTickets[msg.sender][roundNumber] = tickets(msg.sender, ticket);
        for(uint i=0; ticket > i; i++){
            entries.push(msg.sender);
            numOfTicketsSold++;
        }
        }
        else
        {
        ownerOfTickets[msg.sender][roundNumber].numOfTickets += ticket;
        
        for(uint j=0; ticket > j; j++){
            entries.push(msg.sender);
            numOfTicketsSold++;
            
        }
        }
        }
        
        else{
        require(token.transferFrom(msg.sender, owner, amount));
        }
    }
    
    function distributePrize() public payable onlyWhenTimeIsUpOrAllTicketsSold{      
        if (numOfTicketsSold > 0){
        uint randomNumber = uint(keccak256(abi.encodePacked(now, msg.sender))).mod(numOfTicketsSold);
        winner.push(entries[randomNumber]);
        address winnerAddress = winner[roundNumber];
        uint ownerShare = potTotal.mul(5).div(100);
        uint potShare = potTotal.mul(10).div(100);
        uint winnerShare = potTotal.sub(ownerShare.add(potShare));
        require(token.transfer(owner, ownerShare));
        require(token.transfer(winnerAddress, winnerShare));
        potTotal=potShare;
        }
 
        else{
        winner.push(address(0));
        }

	    delete entries;
        roundNumber++;
        numOfTicketsSold = 0;
        players=0;
        unlockTime= now + 7 days;
    }
    
    function terminateContract() public payable onlyOwner{
        for(uint k=0; players > k; k++)
        {
        uint refund = ownerOfTickets[playerAddress[k]][roundNumber].numOfTickets;
        require(token.transfer(playerAddress[k], refund.mul(100000000000000000000)));
        }
        potTotal = token.balanceOf(address(this));
        require(token.transfer(owner, potTotal));
        selfdestruct(owner);
    }
    
    function getLastWinner() public view returns (address){
        if(roundNumber == 0){
        return winner[roundNumber];
        }
        else{
            return winner[roundNumber.sub(1)];
        }
    }
    
    function getTicketNum(address ticketHolder) public view returns(uint) {
        return ownerOfTickets[ticketHolder][roundNumber].numOfTickets;
        
    }
    
    function timeLeft() public view returns(uint) {
        if (unlockTime >= now) {
            return unlockTime.sub(now);
        }
        else {
            return 0;
        }
    }
    
    modifier onlyWhenTimeIsUpOrAllTicketsSold{
        require (unlockTime < now);
        _;
    }
    
    modifier onlyWhenTimeIsLeft{
        require (unlockTime > now);
        _;
    }
    
}


// File: Owned.sol



pragma solidity 0.5.4;

contract Owned {

address payable  owner;
address payable newOwner;


constructor() public{
    owner = msg.sender;
}


function changeOwner(address payable _newOwner) public onlyOwner {

    newOwner = _newOwner;

}

function acceptOwnership() public{
    if (msg.sender == newOwner) {
        owner = newOwner;
        newOwner = address(0);
    }
}

modifier onlyOwner() {
    require(msg.sender == owner);
    _;
}
}

// File: SafeMath.sol



pragma solidity 0.5.4;

/**
 * @title SafeMath
 * @dev Unsigned math operations with safety checks that revert on error
 */
library SafeMath {
    /**
    * @dev Multiplies two unsigned integers, reverts on overflow.
    */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b);

        return c;
    }

    /**
    * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
    */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
    * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
    */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a);
        uint256 c = a - b;

        return c;
    }

    /**
    * @dev Adds two unsigned integers, reverts on overflow.
    */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);

        return c;
    }

    /**
    * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
    * reverts when dividing by zero.
    */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0);
        return a % b;
    }
}