contract LionKing is ERC20("KittySwaps Lion King", "LION"), Ownable {
    using SafeMath for uint256;
    IERC20 public erc20;

    // whether Grassland is opened or not
    bool public isOpen = true;
    bool public isAllow = false;
    // amount of blocks between each unlock
    uint256 public blocksBetween;
    // next period that Lionking will remain opened
    uint256[2] public openPeriod;    

    event Opened(address indexed who);
    event Closed(address indexed who);
    event Joined(address indexed who, uint256 amount);
    event Left(address indexed who, uint256 amount);

    constructor(uint256 _blocksBetween, uint256[2] memory _openPeriod, IERC20 _erc20) public {
      blocksBetween = _blocksBetween;
      openPeriod = _openPeriod;
      erc20 = _erc20;
    }

    modifier validateGrassland() {
      require(isOpen, "grassland closed");
      _;
    }

    modifier validateAllow() {
      require(isAllow, "not allowed");
      _;
    }

    function pendingERC20() external view returns (uint256) {
      uint256 totalShares = totalSupply();
      if (totalShares == 0) {
        return 0;
      }

      uint256 lionShare = balanceOf(msg.sender);
      uint256 what = lionShare.mul(erc20.balanceOf(address(this))).div(totalShares);

      return what;
    }

    function openGrassland() external validateAllow {
      require(block.number > openPeriod[0] && block.number < openPeriod[1], "Not ready to open");
      require(isOpen == false, "Already opened");
      isOpen = true;

      emit Opened(msg.sender);
    }

    function closeGrassland() external validateAllow {
      require(block.number > openPeriod[1], "Still in open period");
      require( isOpen == true, "Already closed");
      // adds amount of blocks until next opening (defined by governance)
      openPeriod[0] = openPeriod[1] + blocksBetween;
      // grassland remains open for ~1 day
      openPeriod[1] = openPeriod[0] + 6400;
      isOpen = false;

      emit Closed(msg.sender);
    }

    // allows governance to start or stop grassland
    function govAllow() public onlyOwner {
      require( isAllow == false, "Already allowed");
      isAllow = true;
    }
    function govForbid() public onlyOwner {
      require( isAllow == true, "Already forbidden");
      isAllow = false;
    }
    function govOpen() public onlyOwner {
      require( isOpen == false, "Already opened");
      isOpen = true;
    }
    function govClose() public onlyOwner {
      require( isOpen == true, "Already closed");
      isOpen = false;
    }

    // allows governance to update openPeriod
    function setOpenPeriod(uint256 _newStart, uint256 _newEnd) public onlyOwner {
      openPeriod[0] = _newStart;
      openPeriod[1] = _newEnd;
    }

    // allows governance to update blocksBetween
    function setBlocksBetween(uint256 _newValue) public onlyOwner {
      blocksBetween = _newValue;
    }

    // Opens the Grassland and collects ERC20
    function enter(uint256 _amount) public validateGrassland {
        uint256 totalERC20 = erc20.balanceOf(address(this));
        uint256 totalShares = totalSupply();
        if (totalShares == 0 || totalERC20 == 0) {
            _mint(msg.sender, _amount);
        } else {
            uint256 what = _amount.mul(totalShares).div(totalERC20);
            _mint(msg.sender, what);
        }
        erc20.transferFrom(msg.sender, address(this), _amount);

        emit Joined(msg.sender, _amount);
    }

    // Leave the grassland. Claim back your ERC20s.
    function leave(uint256 _share) public validateGrassland {
        uint256 totalShares = totalSupply();
        uint256 what = _share.mul(erc20.balanceOf(address(this))).div(totalShares);
        _burn(msg.sender, _share);
        erc20.transfer(msg.sender, what);

        emit Left(msg.sender, what);
    }
}
function setOpenPeriod(uint256 _newStart, uint256 _newEnd) public onlyOwner {
      openPeriod[0] = _newStart;
      openPeriod[1] = _newEnd;
    }
// allows governance to update openPeriod