contract BOOTY is IBOOTY, ERC20, Ownable, Pausable {

  using SafeMath for uint256;

  event BootyPaid(address indexed user, uint256 bootyReward);

  uint256 public constant CAPTAIN_DAILY_BOOTY = 300 ether;
  uint256 public constant CREW_DAILY_BOOTY = 100 ether;

  mapping(address => uint256) internal lastClaimTimestamp;
  mapping(address => bool) internal admins;
  mapping(address => uint256) public bootyRewards;

  /// LEGENDLIST SETUP ///
  struct Legendlist {
    bool isLegendlisted;
    uint16 qtyMinted;
    }
  mapping(address => Legendlist) private _legendlistAddresses;


  IBOOTY public booty;
  IPiRats public potm;
  
  constructor() ERC20("BOOTY", "BOOTY") {
    _pause();
  }

  /// MINT/BURN ///

  function claimGift(address to) external override whenNotPaused {
    require(admins[_msgSender()], "Only admins - claimBooty");
    uint256 amount = 1000 ether;
    _mint(to, amount);
  }

  function mint(address to, uint256 amount) public whenNotPaused {
    require(admins[_msgSender()], "Only admins - mint");
    _mint(to, amount);
  }

  function burn(address from, uint256 amount) internal whenNotPaused {
    require(admins[_msgSender()], "Only admins - burn");
    _burn(from, amount);
  }
  /// CLAIMING $BOOTY /// 

  function claimBooty(address owner) external override whenNotPaused {
    require(admins[_msgSender()], "Only admins - claimBooty");
    uint256 totalPending = pendingClaimable(owner);    
    bootyRewards[owner] += totalPending;
	  uint256 bootyReward = bootyRewards[owner];
    require(bootyReward > 0, "Dont have any BOOTY");
		mint(owner, bootyReward);
		emit BootyPaid(owner, bootyReward);
    lastClaimTimestamp[owner] = block.timestamp;
    bootyRewards[owner] = 0;
  } 

  function pendingClaimable(address owner) internal view returns (uint256 pending){
    uint256 _lastClaim = lastClaimTimestamp[owner];
    pending = (earningRate(owner) * (block.timestamp - _lastClaim)) / 86400;
  }

  function earningRate(address owner) internal view returns(uint256 dailyRate) {
    uint32 totalPiRats = potm.getBalanceCrew(owner) + potm.getBalanceCaptain(owner);
    uint256 _dailyRate = ((potm.getBalanceCrew(owner) * CREW_DAILY_BOOTY) + (potm.getBalanceCaptain(owner) * CAPTAIN_DAILY_BOOTY) + (potm.getTotalRank(owner)*(10**18)));
    if (totalPiRats > 20) {
        dailyRate = _dailyRate / 2;
    } else if (totalPiRats > 50) {
        dailyRate = _dailyRate / 4;
    } else {
        dailyRate = _dailyRate;
    }
  }

  /// OVERRIDE ///

  function showPendingClaimable(address owner) external view override returns (uint256 pending){
    pending = pendingClaimable(owner);
  } 

  function showEarningRate(address owner) external view override returns (uint256 dailyRate){
    dailyRate = earningRate(owner);
  } 

  function burnExternal(address from, uint256 amount) external whenNotPaused override {
    require(admins[_msgSender()], "Only admins can burnExternal");
    burn(from, amount);
  }

  function initTimeStamp(address owner, uint256 timeStamp) external whenNotPaused override {
    require(admins[_msgSender()], "Only admins can call initTimeStamp");
    uint256 _lastClaim = lastClaimTimestamp[owner];
    if (_lastClaim > 0) {
      lastClaimTimestamp[owner] = _lastClaim;
    } else {
      lastClaimTimestamp[owner] = timeStamp;
    }
  }

  function transferFrom(address sender, address recipient, uint256 amount) public virtual override(ERC20, IBOOTY) returns (bool) {
    require(admins[_msgSender()], "Only admins can call transferFrom");
    if(admins[_msgSender()]) {
      _transfer(sender, recipient, amount);
      return true;
    }
    return super.transferFrom(sender, recipient, amount);
  }

  function balanceOf(address account) public view override(ERC20, IBOOTY) returns (uint256) {
    return super.balanceOf(account);
  }

  /// ADMIN ///

  function setPaused(bool _paused) external onlyOwner {
    if (_paused) _pause();
    else _unpause();
  }

  function setContracts(address _potm) external onlyOwner {   
    potm = IPiRats(_potm);
    }

  function addAdmin(address addr) external onlyOwner {
    admins[addr] = true;
  }

  function removeAdmin(address addr) external onlyOwner {
    admins[addr] = false;
  }

}
//////////////////////
function claimBooty(address owner) external override whenNotPaused {
  require(admins[_msgSender()], "Only admins - claimBooty");
  uint256 totalPending = pendingClaimable(owner);    
  bootyRewards[owner] += totalPending;
 uint256 bootyReward = bootyRewards[owner];
  require(bootyReward > 0, "Dont have any BOOTY");
mint(owner, bootyReward);
emit BootyPaid(owner, bootyReward);
  lastClaimTimestamp[owner] = block.timestamp;
  bootyRewards[owner] = 0;
} 

/// CLAIMING $BOOTY /// 