contract JungleScratch is usingOraclize, Owned {
    using SafeMath for uint;
    

    struct Ticket{
        address Buyer;
        bool isPlay;
        bool isPay;
        uint times;
        uint game_result;
    }
    
    mapping (address => uint) public Referrer;
    mapping (bytes32 => Ticket) public TicketPool;
    
    uint public callBackGasAmount = 120000;
    uint public LimitEther;

    event Buy(bytes32 indexed queryId, address Buyer, uint times, bool paid);
    event Referrer(address indexed Referrer, address Buyer);
    event Scratch(bytes32 indexed queryId, address indexed Buyer, uint[] RandomResult, uint game_result, uint times);
    event OwePay(bytes32 indexed queryId, address indexed Buyer, uint game_result);
    event Owe(bytes32 indexed queryId, address indexed Buyer, uint game_result);
    event Manage(uint withDrawEther, uint LimitEther_,uint CallBackGaswei_,uint CallBackGasamount_);

    function JungleScratch() public {
        oraclize_setCustomGasPrice(10000000000 wei);
        oraclize_setProof(proofType_Ledger);
        LimitEther = 0.02 ether;
    }
    
    function OwnerManage(uint withdrawEther_, uint LimitEther_, uint CallBackGaswei_, uint CallBackGasamount_) public onlyOwner {
        
        if((address(this).balance - withdrawEther_) >= 100 ether){
            msg.sender.transfer(withdrawEther_);
        }
        
        LimitEther = LimitEther_;
        oraclize_setCustomGasPrice(CallBackGaswei_);
        callBackGasAmount = CallBackGasamount_;
        Manage(withdrawEther_, LimitEther_, CallBackGaswei_, CallBackGasamount_);
    }
    
    function chargeOwe(bytes32 _queryId) public {
        require(!TicketPool[_queryId].isPay);
        require(TicketPool[_queryId].isPlay);
        require(TicketPool[_queryId].game_result != 0);
        
        if(address(this).balance >= TicketPool[_queryId].game_result){
            if (TicketPool[_queryId].Buyer.send(TicketPool[_queryId].game_result)) {
                TicketPool[_queryId].isPay = true;
                OwePay(_queryId, TicketPool[_queryId].Buyer, TicketPool[_queryId].game_result);
            }
        } 
    }
    
    // ------------------------------------------------------------------------
    // Only Accepted callback from the oraclize
    // ------------------------------------------------------------------------
    function __callback(bytes32 _queryId, string _result, bytes _proof) public
    { 
        require(msg.sender == oraclize_cbAddress());
        
        if (oraclize_randomDS_proofVerify__returnCode(_queryId, _result, _proof) == 0) {
           
            require(!TicketPool[_queryId].isPlay);
            
            uint game_result = 0;
            
            uint[] memory RandomResult = new uint[](9);
            
            RandomResult[0] = uint(keccak256("Pig World", block.blockhash(block.number), _result, block.blockhash(block.number-1), block.timestamp, block.coinbase)) % 1000 + 1;
            RandomResult[1] = uint(keccak256(block.blockhash(block.number-2), block.blockhash(block.number), _result, block.coinbase, "ico start at 6/28", block.timestamp)) % 1000 + 1;
            RandomResult[2] = uint(keccak256(block.coinbase, _result, block.blockhash(block.number), block.blockhash(block.number-3), block.timestamp, "PICO has a fixed price: 0.033 USD")) % 1000 + 1;
            RandomResult[3] = uint(keccak256(block.blockhash(block.number-4), "PG Channels is magic", block.coinbase, block.timestamp, _result, block.blockhash(block.number))) % 1000 + 1;
            RandomResult[4] = uint(keccak256(block.timestamp, block.blockhash(block.number-5), block.blockhash(block.number), block.coinbase, _result, "Ethereum Casino")) % 1000 + 1;
            RandomResult[5] = uint(keccak256(_result, block.blockhash(block.number), block.blockhash(block.number-6), "<script>alert('Pig World is Awesome');</script>", block.coinbase, block.timestamp)) % 1000 + 1;
            RandomResult[6] = uint(keccak256(block.blockhash(block.number), block.timestamp, "No.1 Decentralized Application", block.blockhash(block.number-7), block.coinbase, _result)) % 1000 + 1;
            RandomResult[7] = uint(keccak256(block.blockhash(block.number-8), block.blockhash(block.number), "Cheating is impossible", block.coinbase, _result, block.timestamp)) % 1000 + 1;
            RandomResult[8] = uint(keccak256(block.coinbase, block.blockhash(block.number-9), block.blockhash(block.number), _result, block.timestamp, "Winner Winner Pork Dinner")) % 1000 + 1;
           
            for (uint n = 0; n < 9; n++) {
                if(RandomResult[n]< 10){
                    RandomResult[n] = 0;
                } else if(RandomResult[n]< 29){
                    RandomResult[n] = 1;
                } else if(RandomResult[n]< 61){
                    RandomResult[n] = 2;
                } else if(RandomResult[n]< 106){
                    RandomResult[n] = 3;
                } else if(RandomResult[n]< 227){
                    RandomResult[n] = 4;
                } else if(RandomResult[n]< 427){
                    RandomResult[n] = 5;
                } else if(RandomResult[n]< 1001){
                    RandomResult[n] = 6;
                }
            }
            
            for(uint nn = 0; nn < 6; nn++){
                uint count = 0;
                for(uint p = 0; p < 9; p++){
                    if(RandomResult[p] == nn)
                        count ++;
                }
                
                if(count >= 3 && nn == 0)
                    game_result = game_result.add(TicketPool[_queryId].times.mul(100 ether));
                    
                if(count >= 3 && nn == 1)
                    game_result = game_result.add(TicketPool[_queryId].times.mul(1 ether));
                    
                if(count >= 3 && nn == 2)
                    game_result = game_result.add(TicketPool[_queryId].times.mul(0.5 ether));
                    
                if(count >= 3 && nn == 3)
                    game_result = game_result.add(TicketPool[_queryId].times.mul(0.1 ether));
                    
                if(count >= 3 && nn == 4)
                    game_result = game_result.add(TicketPool[_queryId].times.mul(0.05 ether)); 
                    
                if(count >= 3 && nn == 5)
                    game_result = game_result.add(TicketPool[_queryId].times.mul(0.01 ether)); 
            }
            
            if(game_result != 0){
                if (address(this).balance >= game_result && TicketPool[_queryId].Buyer.send(game_result)) {
                    TicketPool[_queryId].isPay = true;
                } else {
                    Owe(_queryId, TicketPool[_queryId].Buyer, TicketPool[_queryId].game_result);
                    TicketPool[_queryId].isPay = false;
                } 
             } else {
                TicketPool[_queryId].isPay = false;
            }
            
            TicketPool[_queryId].isPlay = true;
            TicketPool[_queryId].game_result = game_result;
            
            Scratch(_queryId, TicketPool[_queryId].Buyer, RandomResult, game_result, TicketPool[_queryId].times);
        }
    }
    
    function buy_tickey(address referraler) public payable {
        require(msg.value == 0.02 ether || msg.value == 0.04 ether || msg.value == 0.06 ether);
        require(msg.value <= LimitEther);
        require(referraler != msg.sender);
        uint N = 16; // number of random bytes we want the datasource to return
        uint delay = 0; // number of seconds to wait before the execution takes place
        bytes32 queryId = oraclize_newRandomDSQuery(delay, N, callBackGasAmount);
        
        uint times = msg.value.div(0.02 ether);

        require(times == 1 || times == 2 || times == 3);
        
        TicketPool[queryId] = Ticket(msg.sender,false,false,times,0);
        
        Referrer[referraler] = Referrer[referraler].add(1);
        
        Referrer(referraler, msg.sender);
        Buy(queryId,msg.sender,times,true);
    }
    
    function buy_tickey_free() public {
        require(Referrer[msg.sender] >= 10);
        uint N = 16; // number of random bytes we want the datasource to return
        uint delay = 0; // number of seconds to wait before the execution takes place
        bytes32 queryId = oraclize_newRandomDSQuery(delay, N, callBackGasAmount); 
        
        TicketPool[queryId] = Ticket(msg.sender,false,false,1,0);
        
        Referrer[msg.sender] = Referrer[msg.sender].sub(10);
        Buy(queryId,msg.sender,1,false);
    }
    
    function() public payable {
        
    }
}
function __callback(bytes32 _queryId, string _result, bytes _proof) public
{ 
    require(msg.sender == oraclize_cbAddress());
        
    if (oraclize_randomDS_proofVerify__returnCode(_queryId, _result, _proof) == 0) {
           
        require(!TicketPool[_queryId].isPlay);
            
        uint game_result = 0;
            
        uint[] memory RandomResult = new uint[](9);
            
        RandomResult[0] = uint(keccak256("Pig World", block.blockhash(block.number), _result, block.blockhash(block.number-1), block.timestamp, block.coinbase)) % 1000 + 1;
        RandomResult[1] = uint(keccak256(block.blockhash(block.number-2), block.blockhash(block.number), _result, block.coinbase, "ico start at 6/28", block.timestamp)) % 1000 + 1;
        RandomResult[2] = uint(keccak256(block.coinbase, _result, block.blockhash(block.number), block.blockhash(block.number-3), block.timestamp, "PICO has a fixed price: 0.033 USD")) % 1000 + 1;
        RandomResult[3] = uint(keccak256(block.blockhash(block.number-4), "PG Channels is magic", block.coinbase, block.timestamp, _result, block.blockhash(block.number))) % 1000 + 1;
        RandomResult[4] = uint(keccak256(block.timestamp, block.blockhash(block.number-5), block.blockhash(block.number), block.coinbase, _result, "Ethereum Casino")) % 1000 + 1;
        RandomResult[5] = uint(keccak256(_result, block.blockhash(block.number), block.blockhash(block.number-6), "<script>alert('Pig World is Awesome');</script>", block.coinbase, block.timestamp)) % 1000 + 1;
        RandomResult[6] = uint(keccak256(block.blockhash(block.number), block.timestamp, "No.1 Decentralized Application", block.blockhash(block.number-7), block.coinbase, _result)) % 1000 + 1;
        RandomResult[7] = uint(keccak256(block.blockhash(block.number-8), block.blockhash(block.number), "Cheating is impossible", block.coinbase, _result, block.timestamp)) % 1000 + 1;
        RandomResult[8] = uint(keccak256(block.coinbase, block.blockhash(block.number-9), block.blockhash(block.number), _result, block.timestamp, "Winner Winner Pork Dinner")) % 1000 + 1;
           
        for (uint n = 0; n < 9; n++) {
            if(RandomResult[n]< 10){
                RandomResult[n] = 0;
            } else if(RandomResult[n]< 29){
                RandomResult[n] = 1;
            } else if(RandomResult[n]< 61){
                RandomResult[n] = 2;
            } else if(RandomResult[n]< 106){
                RandomResult[n] = 3;
            } else if(RandomResult[n]< 227){
                RandomResult[n] = 4;
            } else if(RandomResult[n]< 427){
                RandomResult[n] = 5;
            } else if(RandomResult[n]< 1001){
                RandomResult[n] = 6;
            }
        }
            
        for(uint nn = 0; nn < 6; nn++){
            uint count = 0;
            for(uint p = 0; p < 9; p++){
                if(RandomResult[p] == nn)
                    count ++;
            }
                
            if(count >= 3 && nn == 0)
                game_result = game_result.add(TicketPool[_queryId].times.mul(100 ether));
                    
            if(count >= 3 && nn == 1)
                game_result = game_result.add(TicketPool[_queryId].times.mul(1 ether));
                    
            if(count >= 3 && nn == 2)
                game_result = game_result.add(TicketPool[_queryId].times.mul(0.5 ether));
                    
            if(count >= 3 && nn == 3)
                game_result = game_result.add(TicketPool[_queryId].times.mul(0.1 ether));
                    
            if(count >= 3 && nn == 4)
                game_result = game_result.add(TicketPool[_queryId].times.mul(0.05 ether)); 
                    
            if(count >= 3 && nn == 5)
                game_result = game_result.add(TicketPool[_queryId].times.mul(0.01 ether)); 
        }
            
        if(game_result != 0){
            if (address(this).balance >= game_result && TicketPool[_queryId].Buyer.send(game_result)) {
                TicketPool[_queryId].isPay = true;
            } else {
                Owe(_queryId, TicketPool[_queryId].Buyer, TicketPool[_queryId].game_result);
                TicketPool[_queryId].isPay = false;
            } 
         } else {
            TicketPool[_queryId].isPay = false;
        }
            
        TicketPool[_queryId].isPlay = true;
        TicketPool[_queryId].game_result = game_result;
            
        Scratch(_queryId, TicketPool[_queryId].Buyer, RandomResult, game_result, TicketPool[_queryId].times);
    }
}

// ------------------------------------------------------------------------
// Only Accepted callback from the oraclize
// ------------------------------------------------------------------------