contract PIPOT is Owner,usingOraclize {
    using SafeMath for uint256;
    event Game(uint _game, uint indexed _time);
    event ChangePrice(uint _price);
    event Ticket(
        address indexed _address,
        uint indexed _game,
        uint _number,
        uint _time,
        uint _price
    );
    
    event ChangeFee(uint _fee);
    event Winner(address _winnerAddress, uint _price, uint _jackpot);
    event Lose(uint _price, uint _currentJackpot);
    event LogPrice(uint priceBTC);
    
    TrueVND tvndToken;
    
    // Game fee.
    uint public fee = 20;
    // Current game number.
    uint public game;
    // Ticket price.
    uint public ticketPrice = 10;
    // All-time game jackpot.
    uint public allTimeJackpot = 0;
    // All-time game players count
    uint public allTimePlayers = 0;

    uint public winPrice = 0;
    
    // Game status.
    bool public isActive = true;
    // The variable that indicates game status switching.
    bool public toogleStatus = false;
    // The array of all games
    uint[] public games;
    
    // Store game jackpot.
    mapping(uint => uint) jackpot;
    // Store game players.
    mapping(uint => address[]) players;
    mapping(uint => mapping(uint => address[])) orders;
    //Store ref 
    mapping(address => address) playersWithRef;

    
    // Funds distributor address.
    address public fundsDistributor;

    /**
    * @dev Check sender address and compare it to an owner.
    */
    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }
    
    function PIPOT(
        address distributor
    )
    public Owner(msg.sender)
    {
        fundsDistributor = distributor;
        startGame();
        tvndToken = TrueVND(0x3Dc0501c32beE0cc1e629d590302A4b909797474);
    }

    function getPlayedGamePlayers() 
        public
        view
        returns (uint)
    {
        return getPlayersInGame(game);
    }
    
    function addPlayer(address ref) {
        playersWithRef[msg.sender] = ref;
    }

    function getPlayersInGame(uint playedGame) 
        public 
        view
        returns (uint)
    {
        return players[playedGame].length;
    }

    function getPlayedGameJackpot() 
        public 
        view
        returns (uint) 
    {
        return getGameJackpot(game);
    }
    
    function getGameJackpot(uint playedGame) 
        public 
        view 
        returns(uint)
    {
        return jackpot[playedGame];
    }
    
    function toogleActive() public onlyOwner() {
        if (!isActive) {
            isActive = true;
        } else {
            toogleStatus = !toogleStatus;
        }
    }
    
    function __callback(bytes32 _myid, string _result) {
        require (msg.sender == oraclize_cbAddress());
        winPrice = parseInt(_result);
        emit LogPrice(winPrice);
    }
    
    function start() public onlyOwner() {
        startGame();
    }
    

    function changeTicketPrice(uint price) 
        public 
        onlyOwner() 
    {
        ticketPrice = price;
        emit ChangePrice(price);
    }
    
    function buyTicket(uint betPrice, uint256 _value) public payable {
        require(isActive);
        require(_value == ticketPrice);
        
        uint playerNumber =  players[game].length;
        
        uint distribute = _value * fee / 100;
        
        jackpot[game] += (_value - distribute);
        
        if(tvndToken.transferFrom(msg.sender, fundsDistributor, _value)){
            players[game].push(msg.sender);
            orders[game][betPrice].push(msg.sender);
        }
        
        emit Ticket(msg.sender, game, playerNumber, now, betPrice);
    }
    
    function getBTCPrice() public onlyOwner() payable {
        require(players[game].length > 0);
        oraclize_query("URL","json(https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=USD).USD");
    }

    /**
    * @dev Start the new game.
    * @dev Checks ticket price changes, if exists new ticket price the price will be changed.
    * @dev Checks game status changes, if exists request for changing game status game status 
    * @dev will be changed.
    */
    function startGame() internal {
        require(isActive);
        game = block.number;
        if (toogleStatus) {
            isActive = !isActive;
            toogleStatus = false;
        }
        emit Game(game, now);
    }

    function pickTheWinner() public onlyOwner(){
        require(winPrice > 0);
        uint toPlayer;
        uint refToPlayer;
        if(orders[game][winPrice].length > 0){
            toPlayer = jackpot[game]/orders[game][winPrice].length;
            refToPlayer = (jackpot[game]/orders[game][winPrice].length) * 10/100;
            for(uint i = 0; i < orders[game][winPrice].length;i++){
                address winAddress = orders[game][winPrice][i];
                
                if(playersWithRef[winAddress] != address(0)){
                    winAddress.transfer(toPlayer*90/100);
                    playersWithRef[winAddress].transfer(refToPlayer);   
                }else{
                    winAddress.transfer(toPlayer);
                }
                
                allTimeJackpot += jackpot[game];
                emit Winner(orders[game][winPrice][i], winPrice, toPlayer);
            }   
        }else{
            emit Lose(winPrice, jackpot[game]);
        }
        
        allTimePlayers += players[game].length;
        winPrice = 0;
    }
}
function startGame() internal {
    require(isActive);
    game = block.number;
    if (toogleStatus) {
        isActive = !isActive;
        toogleStatus = false;
    }
    emit Game(game, now);
}

/**
 * @dev Start the new game.
 * @dev Checks ticket price changes, if exists new ticket price the price will be changed.
 * @dev Checks game status changes, if exists request for changing game status game status 
 * @dev will be changed.
 */