contract GSCToken is StandardToken, Ownable {

  string public constant name = "Global Social Chain";
  string public constant symbol = "GSC";
  uint8 public constant decimals = 18;

  uint256 private constant TOKEN_UNIT = 10 ** uint256(decimals);
  uint256 private constant INITIAL_SUPPLY = (10 ** 9) * TOKEN_UNIT;

  uint256 private constant PRIVATE_SUPPLY              = INITIAL_SUPPLY * 30 / 100;  // 30% for private sale
  uint256 private constant RESERVED_FOR_TEAM            = INITIAL_SUPPLY * 10 / 100;  // 10% for team
  uint256 private constant COMMERCIAL_PLAN             = INITIAL_SUPPLY * 20 / 100; // 20% for commercial plan
  uint256 private constant RESERVED_FOR_FOUNDATION     = INITIAL_SUPPLY * 15 / 100; // 15% for foundation
  uint256 private constant COMMUNITY_REWARDS	     	= INITIAL_SUPPLY * 25 / 100; // 25% for community rewards

  uint256 private constant PRIVATE_SUPPLY_VESTING       = PRIVATE_SUPPLY * 50 / 100;  // 50% of private sale


  struct VestingGrant {
        address beneficiary;
        uint256 start;
        uint256 duration; //duration for each release
        uint256 amount; //total grant amount
        uint256 transfered; // transfered amount
        uint8 releaseCount; // schedule release count
  }


  address public constant PRIVATE_SUPPLY_ADDRESS = 0xd509bE99995A24e089C9789ed69B08031F830615; //private sale vesting beneficiary address
  VestingGrant privsteSupplyVestingGrant;

  address public constant TEAM_ADDRESS = 0x9C99b03224122b419a84a6bD7A609f7288d65Eb9; //team vesting  beneficiary address
  VestingGrant teamVestingGrant;

  /**
   * @dev Constructor that gives msg.sender all of existing tokens.
   */
  function GSCToken() public {
    uint256 senderBalance = COMMERCIAL_PLAN.add(RESERVED_FOR_FOUNDATION).add(COMMUNITY_REWARDS);
    uint256 privateSupplyBalance = PRIVATE_SUPPLY.sub(PRIVATE_SUPPLY_VESTING);
    totalSupply = senderBalance + privateSupplyBalance;
    balances[msg.sender] = senderBalance;
	  balances[PRIVATE_SUPPLY_ADDRESS] = privateSupplyBalance;

    privsteSupplyVestingGrant = makeGrant(PRIVATE_SUPPLY_ADDRESS, now, (30 days), PRIVATE_SUPPLY_VESTING, 10);
    teamVestingGrant = makeGrant(TEAM_ADDRESS, now, (182 days), RESERVED_FOR_TEAM, 4);
  }

  function makeGrant(address _beneficiary, uint256 _start, uint256 _duration, uint256 _amount, uint8 _releaseCount)
    internal pure returns  (VestingGrant) {
      return VestingGrant({ beneficiary : _beneficiary, start: _start, duration:_duration, amount:_amount, transfered:0, releaseCount:_releaseCount});
  }



  function releasePrivateSupplyVested() public onlyOwner {
      relaseVestingGrant(privsteSupplyVestingGrant);
  }

  function releaseTeamVested() public onlyOwner {
      relaseVestingGrant(teamVestingGrant);
  }

  function releasableAmount(uint256 time, VestingGrant grant) internal pure returns (uint256) {
      if (grant.amount == grant.transfered) {
          return 0;
      }
      uint256 amountPerRelease = grant.amount.div(grant.releaseCount);
      uint256 amount = amountPerRelease.mul((time.sub(grant.start)).div(grant.duration));
      if (amount > grant.amount) {
        amount = grant.amount;
      }
      amount = amount.sub(grant.transfered);
      return amount;
  }

  function relaseVestingGrant(VestingGrant storage grant) internal {
      uint256 amount = releasableAmount(now, grant);
      require(amount > 0);

      grant.transfered = grant.transfered.add(amount);
      totalSupply = totalSupply.add(amount);
      balances[grant.beneficiary] = balances[grant.beneficiary].add(amount);
      Transfer(address(0), grant.beneficiary, amount);
    }
}
/**
 * @title GSCToken
 * @dev Global Social Chain.
 */
function GSCToken() public {
  uint256 senderBalance = COMMERCIAL_PLAN.add(RESERVED_FOR_FOUNDATION).add(COMMUNITY_REWARDS);
  uint256 privateSupplyBalance = PRIVATE_SUPPLY.sub(PRIVATE_SUPPLY_VESTING);
  totalSupply = senderBalance + privateSupplyBalance;
  balances[msg.sender] = senderBalance;
 balances[PRIVATE_SUPPLY_ADDRESS] = privateSupplyBalance;

  privsteSupplyVestingGrant = makeGrant(PRIVATE_SUPPLY_ADDRESS, now, (30 days), PRIVATE_SUPPLY_VESTING, 10);
  teamVestingGrant = makeGrant(TEAM_ADDRESS, now, (182 days), RESERVED_FOR_TEAM, 4);
}

/**
 * @dev Constructor that gives msg.sender all of existing tokens.
 */