contract TokenVesting is Ownable {
  using SafeMath for uint256;

  event Vested(address beneficiary, uint256 amount);
  event Released(address beneficiary, uint256 amount);

  struct Balance {
      uint256 value;
      uint256 start;
      uint256 currentPeriod;
  }

  mapping(address => Balance) private balances;
  mapping (address => uint256) private released;
  uint256 private period;
  uint256 private duration;
  mapping (uint256 => uint256) private percentagePerPeriod;

  constructor() public {
    owner = msg.sender;
    period = 4;
    duration = 7884000;
    percentagePerPeriod[0] = 15;
    percentagePerPeriod[1] = 20;
    percentagePerPeriod[2] = 30;
    percentagePerPeriod[3] = 35;
  }
  
  function balanceOf(address _owner) public view returns(uint256) {
      return balances[_owner].value.sub(released[_owner]);
  }
    /**
   * @notice Vesting token to beneficiary but not released yet.
   * ERC20 token which is being vested
   */
  function vesting(address _beneficiary, uint256 _amount) public onlyOwner {
      if(balances[_beneficiary].start == 0){
          balances[_beneficiary].start = now;
      }

      balances[_beneficiary].value = balances[_beneficiary].value.add(_amount);
      emit Vested(_beneficiary, _amount);
  }
  
  /**
   * @notice Transfers vested tokens to beneficiary.
   * ERC20 token which is being vested
   */
  function release(address _beneficiary) public onlyOwner {
    require(balances[_beneficiary].currentPeriod.add(1) <= period);
    require(balances[_beneficiary].value > released[_beneficiary]);
    require(balances[_beneficiary].start != 0);
    require(now >= balances[_beneficiary].start.add((balances[_beneficiary].currentPeriod.add(1) * duration)));

    uint256 amountReleasedThisPeriod = balances[_beneficiary].value.mul(percentagePerPeriod[balances[_beneficiary].currentPeriod]);
    amountReleasedThisPeriod = amountReleasedThisPeriod.div(100);
    released[_beneficiary] = released[_beneficiary].add(amountReleasedThisPeriod);
    balances[_beneficiary].currentPeriod = balances[_beneficiary].currentPeriod.add(1);

    BasicToken(owner).transfer(_beneficiary, amountReleasedThisPeriod);

    emit Released(_beneficiary, amountReleasedThisPeriod);
  }
}
/**
 * @title TokenVesting
 * @dev A token holder contract that can release its token balance gradually like a
 * typical vesting scheme, with a cliff and vesting period. Optionally revocable by the
 * owner.
 */
function vesting(address _beneficiary, uint256 _amount) public onlyOwner {
    if(balances[_beneficiary].start == 0){
        balances[_beneficiary].start = now;
    }

    balances[_beneficiary].value = balances[_beneficiary].value.add(_amount);
    emit Vested(_beneficiary, _amount);
}

/**
 * @notice Vesting token to beneficiary but not released yet.
 * ERC20 token which is being vested
 */