contract YvsLottery is Ownable {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    IERC20 public token;
    
    address[] public players;

    uint256 public lottery_start;
    uint256 public lottery_ticket_price;
    uint256 public lottery_duration;
    bool public lottery_active = false;
    bool public lottery_loop = true;

    address private last_winner;
    uint256 private last_prize_pool;
    uint256 private last_burn_amount;

    /**
    * event to signal lottery start
    */
    event LotteryStarted();

    /**
    * event for signaling lottery winner
    * @param winner address that receives the prize
    * @param amount amount of prize
    */
    event LotteryWinner(address indexed winner, uint256 amount);

    /**
    * event for signaling burn of prize pool
    * @param amount amount of tokens burned
    */
    event LotteryBurned(uint256 amount);

    constructor() public {
        token = IERC20(0xEC681F28f4561c2a9534799AA38E0d36A83Cf478);

        lottery_duration = 24 hours;
        lottery_ticket_price = 250000000000000000;
    }

    // *** EXTERNAL **** //

    function enter() external {
        require(lottery_active, '!active');
        require(token.balanceOf(msg.sender) >= lottery_ticket_price, '!low_balance');

        token.safeTransferFrom(msg.sender, address(this), lottery_ticket_price);

        players.push(msg.sender);
    }

    function pick_winner() external {
        require(block.timestamp >= lottery_start.add(lottery_duration), '!duration');
        require(players.length > 0, '!players');

        uint256 balance = token.balanceOf(address(this));
        uint256 winner_amount = balance.mul(50).div(100);
        uint256 burn_amount = balance.sub(winner_amount);

        uint256 winner_index = pseudo_random() % players.length;
        address winner = players[winner_index];

        token.safeTransfer(winner, winner_amount);
        Burnable(address(token)).burn(burn_amount);

        emit LotteryWinner(winner, winner_amount);
        emit LotteryBurned(burn_amount);

        last_winner = players[winner_index];
        last_prize_pool = winner_amount;
        last_burn_amount = burn_amount;
        players = new address[](0);

        if (lottery_loop && lottery_active) {
            _start();
        } else {
            lottery_active = false;
        }
    }

    // *** INTERNAL **** //

    function _start() internal {
        lottery_start = block.timestamp;
        lottery_active = true;
        emit LotteryStarted();
    }

    // *** RESTRICTED **** //

    function start() public onlyOwner {
        require(!lottery_active, '!active');
        _start();
    }

    function close() external onlyOwner {
        lottery_active = false;
    }

    function set_loop(bool _loop) external onlyOwner {
        lottery_loop = _loop;
    }

    function set_lottery_ticket_price(uint256 _lottery_ticket_price) external onlyOwner {
        require(!lottery_active, '!active');
        lottery_ticket_price = _lottery_ticket_price;
    }

    // *** VIEWS **** //

    function pseudo_random() private view returns (uint256) {
        return uint256(
            keccak256(
                abi.encodePacked(
                    block.difficulty, now, players)));
    }

    function get_prize_pool() public view returns (uint256) {
        return token.balanceOf(address(this)).mul(50).div(100);
    }

    function get_players() public view returns (address[] memory) {
        return players;
    }

    function get_count() public view returns (uint256) {
        return players.length;
    }

    function get_last() public view returns (address, uint256, uint256) {
        return (last_winner, last_prize_pool, last_burn_amount);
    }
}
function start() public onlyOwner {
        require(!lottery_active, '!active');
        _start();
    }
// *** RESTRICTED **** //