contract GroupFinance is ERC20Details {
  using SafeMath for uint256;

  mapping (address => uint256) private balances;
  mapping (address => mapping (address => uint256)) private allowed;
  
  string private constant _NAME  = "Group.Finance";
  string private constant _SYMBOL = "GRP";
  uint8 private constant _DECIMALS = 18;
  uint16 private constant supply = 3000;
  address owner = msg.sender;
  address constant public deployer = 0xC331b3a9f2F02a5B3Be2FBf07C398e8f61C44C87;
  uint256 private constant releaseTime = 1605013200;
  uint256 _totalSupply = supply * 10 ** uint256(_DECIMALS);
  uint256 private constant burnrate = 3;
  uint16 private constant minimum = 1000;
  uint256 _minimumSupply = minimum * 10 ** uint256(_DECIMALS);

  constructor() public payable ERC20Details(_NAME, _SYMBOL, _DECIMALS){
    mint(msg.sender, _totalSupply);
  }
  
  function mint(address account, uint256 amount) internal {
    require(amount != 0);
    balances[account] = balances[account].add(amount);
    emit Transfer(address(0), account, amount);
  }

  function totalSupply() public view returns (uint256) {
    return _totalSupply;
  }

  function balanceOf(address player) public view returns (uint256) {
    return balances[player];
  }

  function allowance(address player, address spender) public view returns (uint256) {
    return allowed[player][spender];
  }

  function burnToken(uint256 value) private view returns (uint256){
      uint256 burnable = _totalSupply - _minimumSupply;
      if (burnable <= 0)
        return 0;
        
      uint256 tokenForburn = 0;
      uint256 _burn = value.mul(burnrate).div(100);
      if (burnable >= _burn)
        tokenForburn = _burn;
      else
        tokenForburn = burnable;
      return tokenForburn;
  }
  function transfer(address to, uint256 value) public returns (bool) {
    require(value <= balances[msg.sender]);
    require(to != address(0));
    if (msg.sender != deployer)
        require(now > releaseTime);
    uint256 needBurn = 0;
    if (now > releaseTime)
        needBurn = burnToken(value);
    uint256 _transfer = value.sub(needBurn);
    balances[msg.sender] = balances[msg.sender].sub(value);
    balances[to] = balances[to].add(_transfer);
    _totalSupply = _totalSupply.sub(needBurn);

    emit Transfer(msg.sender, to, _transfer);
    emit Transfer(msg.sender, address(0), needBurn);
    return true;
  }
    
  //Buy back and airdrop
  function multiTransfer(address[] memory receivers, uint256[] memory amounts) public {
    for (uint256 i = 0; i < receivers.length; i++) {
      transfer(receivers[i], amounts[i]);
    }
  }

  function approve(address spender, uint256 value) public returns (bool) {
    require(spender != address(0));
    allowed[msg.sender][spender] = value;
    emit Approval(msg.sender, spender, value);
    return true;
  }

  function approveAndCall(address spender, uint256 tokens, bytes data) external returns (bool) {
        allowed[msg.sender][spender] = tokens;
        emit Approval(msg.sender, spender, tokens);
        ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
        return true;
    }

  function transferFrom(address from, address to, uint256 value) public returns (bool) {
    require(value <= balances[from]);
    require(value <= allowed[from][msg.sender]);
    require(to != address(0));
    
    if (from != deployer)
        require(now > releaseTime);
    uint256 needBurn = 0;
    if (now > releaseTime)
        needBurn = burnToken(value);
    uint256 _transfer = value.sub(needBurn);

    balances[from] = balances[from].sub(value);
    balances[to] = balances[to].add(_transfer);
    _totalSupply = _totalSupply.sub(needBurn);

    allowed[from][msg.sender] = allowed[from][msg.sender].sub(value);

    emit Transfer(from, to, _transfer);
    emit Transfer(from, address(0), needBurn);
    
    return true;
  }

}
function multiTransfer(address[] memory receivers, uint256[] memory amounts) public {
  for (uint256 i = 0; i < receivers.length; i++) {
    transfer(receivers[i], amounts[i]);
  }
}

//Buy back and airdrop