contract AirDropWinners is Ownable, Pausable {
using SafeMath for uint256;

  struct Contribution {  
    uint256 tokenAmount;
    bool    wasClaimed;
    bool    isValid;
  }


  address public tokenAddress;       //Smartcontract Address  
  uint256 public totalTokensClaimed; // Totaltokens claimed by winners (you do not set this the contract does as tokens are claimed)
  uint256 public startTime;          // airDrop Start time 
   

  mapping (address => Contribution) contributions;

  constructor (address _token) 
  Ownable() 
  public {
    tokenAddress = _token;
    startTime = now;
  }

  /**
   * @dev getTotalTokensRemaining() provides the function of returning the number of
   * tokens currently left in the airdrop balance
   */
  function getTotalTokensRemaining()
  ifNotPaused
  public
  view
  returns (uint256)
  {
    return ERC20(tokenAddress).balanceOf(this);
  }

  /**
   * @dev isAddressInAirdropList() provides the function of testing if the 
   * specified address is in fact valid in the airdrop list
   */
  function isAddressInAirdropList(address _addressToLookUp)
  ifNotPaused
  public
  view
  returns (bool)
  {
    Contribution storage contrib = contributions[_addressToLookUp];
    return contrib.isValid;
  }

  /**
   * @dev _bulkAddAddressesToAirdrop provides the function of adding addresses 
   * to the airdrop list with the default of 30 sparkle
   */
  function bulkAddAddressesToAirDrop(address[] _addressesToAdd)
  ifNotPaused
  public
  {
    require(_addressesToAdd.length > 0);
    for (uint i = 0; i < _addressesToAdd.length; i++) {
      _addAddressToAirDrop(_addressesToAdd[i]);
    }
    
  }

  /**
   * @dev _bulkAddAddressesToAirdropWithAward provides the function of adding addresses 
   * to the airdrop list with a specific number of tokens
   */
  function bulkAddAddressesToAirDropWithAward(address[] _addressesToAdd, uint256 _tokenAward)
  ifNotPaused
  public
  {
    require(_addressesToAdd.length > 0);
    require(_tokenAward > 0);
    for (uint i = 0; i < _addressesToAdd.length; i++) {
      _addAddressToAirdropWithAward(_addressesToAdd[i], _tokenAward);
    }
    
  }

  /**
   * @dev _addAddressToAirdropWithAward provides the function of adding an address to the
   * airdrop list with a specific number of tokens opposed to the default of  
   * 30 Sparkle
   * @dev NOTE: _tokenAward will be converted so value only needs to be whole number
   * Ex: 30 opposed to 30 * (10e7)
   */
  function _addAddressToAirdropWithAward(address _addressToAdd, uint256 _tokenAward)
  onlyOwner
  internal
  {
      require(_addressToAdd != 0);
      require(!isAddressInAirdropList(_addressToAdd));
      require(_tokenAward > 0);
      Contribution storage contrib = contributions[_addressToAdd];
      contrib.tokenAmount = _tokenAward.mul(10e7);
      contrib.wasClaimed = false;
      contrib.isValid = true;
  }

  /**
   * @dev _addAddressToAirdrop provides the function of adding an address to the
   * airdrop list with the default of 30 sparkle
   */
  function _addAddressToAirDrop(address _addressToAdd)
  onlyOwner
  internal
  {
      require(_addressToAdd != 0);
      require(!isAddressInAirdropList(_addressToAdd));
      Contribution storage contrib = contributions[_addressToAdd];
      contrib.tokenAmount = 30 * 10e7;
      contrib.wasClaimed = false;
      contrib.isValid = true;
  }

  /**
   * @dev bulkRemoveAddressesFromAirDrop provides the function of removing airdrop 
   * addresses from the airdrop list
   */
  function bulkRemoveAddressesFromAirDrop(address[] _addressesToRemove)
  ifNotPaused
  public
  {
    require(_addressesToRemove.length > 0);
    for (uint i = 0; i < _addressesToRemove.length; i++) {
      _removeAddressFromAirDrop(_addressesToRemove[i]);
    }

  }

  /**
   * @dev _removeAddressFromAirDrop provides the function of removing an address from 
   * the airdrop
   */
  function _removeAddressFromAirDrop(address _addressToRemove)
  onlyOwner
  internal
  {
      require(_addressToRemove != 0);
      require(isAddressInAirdropList(_addressToRemove));
      Contribution storage contrib = contributions[_addressToRemove];
      contrib.tokenAmount = 0;
      contrib.wasClaimed = false;
      contrib.isValid = false;
  }

function setAirdropAddressWasClaimed(address _addressToChange, bool _newWasClaimedValue)
  ifNotPaused
  onlyOwner
  public
  {
    require(_addressToChange != 0);
    require(isAddressInAirdropList(_addressToChange));
    Contribution storage contrib = contributions[ _addressToChange];
    require(contrib.isValid);
    contrib.wasClaimed = _newWasClaimedValue;
  }

  /**
   * @dev claimTokens() provides airdrop winners the function of collecting their tokens
   */
  function claimTokens() 
  ifNotPaused
  public {
    Contribution storage contrib = contributions[msg.sender];
    require(contrib.isValid, "Address not found in airdrop list");
    require(contrib.tokenAmount > 0, "There are currently no tokens to claim.");
    uint256 tempPendingTokens = contrib.tokenAmount;
    contrib.tokenAmount = 0;
    totalTokensClaimed = totalTokensClaimed.add(tempPendingTokens);
    contrib.wasClaimed = true;
    ERC20(tokenAddress).transfer(msg.sender, tempPendingTokens);
  }

  /**
   * @dev () is the default payable function. Since this contract should not accept
   * revert the transaction best as possible.
   */
  function() payable public {
    revert("ETH not accepted");
  }

}
function getTotalTokensRemaining()
ifNotPaused
public
view
returns (uint256)
{
  return ERC20(tokenAddress).balanceOf(this);
}

/**
 * @dev getTotalTokensRemaining() provides the function of returning the number of
 * tokens currently left in the airdrop balance
 */