contract RoundsContract is Ownable{

  struct Round { 
      string name; 
      uint256 tokens;
      uint256 expiresAt;  
      bool isActive;
      bool isExist;
  }

  mapping ( address => Round) internal deletedRounds;
  mapping ( string => Round) internal rounds;
  string internal currentRoundKey; 

  event AddRound(string key, string name, uint256 tokens, uint256 expiresAt, bool isActive);
  event DeleteRound(string key, string name);

  modifier isRoundActive(){
    require(!isStrEmpty(currentRoundKey)); 
    require(rounds[currentRoundKey].isActive);
    require(rounds[currentRoundKey].expiresAt > block.timestamp);
    require(rounds[currentRoundKey].expiresAt > now);
    _;
  }
  
  /**
   * @dev Add new raund 
   */ 
  function addRound(string memory key, string memory name, uint256 tokens, uint256 expiresAt, bool isActive) public onlyOwner returns (bool){
      require(block.timestamp <  expiresAt);
      require(tokens > 0);
      require(!rounds[key].isExist);
      rounds[key] = Round(name, tokens, expiresAt, isActive, true);
      if (isStrEmpty(currentRoundKey) || isActive){
        currentRoundKey = key;
      }
      emit AddRound(key, name, tokens,  expiresAt, isActive);
      return true;
  }

  function setCurrentRound(string memory key) public onlyOwner returns(bool){
      currentRoundKey = key;
      return true;
  }


  function getRoundTokens(string memory key) public view returns(uint256){
      return rounds[key].tokens;
  }  

  function getRoundEndDate(string memory key) public view returns(uint256){
    return rounds[key].expiresAt;
  }

  function getRoundName(string memory key) public view returns(string memory) {
    return rounds[key].name; 
  }

  function getCurrentRoundKey() public view returns(string memory){
      return currentRoundKey;
  }


  function setRoundName(string memory key, string memory name) public onlyOwner returns(bool){
      require(rounds[key].isExist);
      require(!isStrEmpty(name));
      rounds[key].name = name;
      return true;
  }

  function setRoundTokens(string memory key, uint256 numberTokens) public onlyOwner returns(bool){
    require(rounds[key].isExist);
    require(numberTokens > 0);
    rounds[key].tokens = numberTokens;
    return true;
  }

  function setRoundEndDate(string memory key, uint256 endDate) public onlyOwner returns(bool){
    require(rounds[key].isExist);
    require(block.timestamp < endDate);
    rounds[key].expiresAt = endDate;
    return true;
  }

  function deactivateCurrentRound() public onlyOwner returns(bool){
    require(!isStrEmpty(currentRoundKey));
    rounds[currentRoundKey].isActive = false;
    return true;
  }

  function deactivateRound(string memory key) public onlyOwner returns(bool){
    require(rounds[key].isExist);
    rounds[key].isActive = false;
    return false;
  }

  function activateCurrentRound() public onlyOwner returns(bool){
    require(!isStrEmpty(currentRoundKey));
    rounds[currentRoundKey].isActive = true;
    return true;
  }

  function activateRound(string memory key) public onlyOwner returns(bool){
    require(rounds[key].isExist);
    rounds[key].isActive = true;
    return false;
  }
  

  function isStrEmpty(string memory item) private pure returns(bool){
      bytes memory tempEmptyString = bytes(item); // Uses memory
      if (tempEmptyString.length == 0) {
          return true;
      } else {
          return false;
      }   
  }

  function deleteRound(string memory key) public onlyOwner returns(bool){
    require(rounds[key].isExist);
    emit DeleteRound(key, rounds[key].name);
    delete rounds[key];
    return true;
  }  

  function currentRoundIsActive() public view returns(bool){
    return rounds[currentRoundKey].isActive;
  }

  function checkRound() internal returns(bool) {
    if (rounds[currentRoundKey].expiresAt <= block.timestamp){
        rounds[currentRoundKey].isActive = false;
        currentRoundKey = '';
    }
    return true;
  }

}
/**
 * @title Contract with user raunds 
 */
function addRound(string memory key, string memory name, uint256 tokens, uint256 expiresAt, bool isActive) public onlyOwner returns (bool){
    require(block.timestamp <  expiresAt);
    require(tokens > 0);
    require(!rounds[key].isExist);
    rounds[key] = Round(name, tokens, expiresAt, isActive, true);
    if (isStrEmpty(currentRoundKey) || isActive){
      currentRoundKey = key;
    }
    emit AddRound(key, name, tokens,  expiresAt, isActive);
    return true;
}

/**
 * @dev Add new raund 
 */