contract Syndicate is Ownable{

    uint256 public totalSyndicateShares = 20000;
    uint256 public availableEarlyPlayerShares = 5000;
    uint256 public availableBuyInShares = 5000;
    uint256 public minimumBuyIn = 10;
    uint256 public buyInSharePrice = 500000000000000; // wei = 0.0005 ether
    uint256 public shareCycleSessionSize = 1000; // number of sessions in a share cycle
    uint256 public shareCycleIndex = 0; // current position in share cycle
    uint256 public currentSyndicateValue = 0; // total value of syndicate to be divided among members
    uint256 public numberSyndicateMembers = 0;
    uint256 public syndicatePrecision = 1000000000000000;

    struct member {
        uint256 numShares;
        uint256 profitShare;
     }

    address[] private syndicateMembers;
    mapping(address => member ) private members;

    event ProfitShare(
          uint256 _currentSyndicateValue,
          uint256 _numberSyndicateMembers,
          uint256 _totalOwnedShares,
          uint256 _profitPerShare
    );

    function Syndicate() public {
        members[msg.sender].numShares = 10000; // owner portion
        members[msg.sender].profitShare = 0;
        numberSyndicateMembers = 1;
        syndicateMembers.push(msg.sender);
    }

    // initiates a dividend of necessary, sends
    function claimProfit() public {
      if (members[msg.sender].numShares==0) revert(); // only syndicate members.
      uint256 profitShare = members[msg.sender].profitShare;
      if (profitShare>0){
        members[msg.sender].profitShare = 0;
        msg.sender.transfer(profitShare);
      }
    }

    // distribute profit amonge syndicate members on a percentage share basis
    function distributeProfit() internal {

      uint256 totalOwnedShares = totalSyndicateShares-(availableEarlyPlayerShares+availableBuyInShares);
      uint256 profitPerShare = SafeMath.div(currentSyndicateValue,totalOwnedShares);

      // foreach member , calculate their profitshare
      for(uint i = 0; i< numberSyndicateMembers; i++)
      {
        // do += so that acrues across share cycles.
        members[syndicateMembers[i]].profitShare+=SafeMath.mul(members[syndicateMembers[i]].numShares,profitPerShare);
      }

      // emit a profit share event
      ProfitShare(currentSyndicateValue, numberSyndicateMembers, totalOwnedShares , profitPerShare);

      currentSyndicateValue=0; // all the profit has been divided up
      shareCycleIndex = 0; // restart the share cycle count.
    }

    // allocate syndicate shares up to the limit.
    function allocateEarlyPlayerShare() internal {
        if (availableEarlyPlayerShares==0) return;
		    availableEarlyPlayerShares--;
       	addMember(); // possibly add this member to the syndicate
        members[msg.sender].numShares+=1;

    }

    // add new member of syndicate
    function addMember() internal {
    	 if (members[msg.sender].numShares == 0){
		          syndicateMembers.push(msg.sender);
		          numberSyndicateMembers++;
		    }
    }

    // buy into syndicate
    function buyIntoSyndicate() public payable  {
    		if(msg.value==0 || availableBuyInShares==0) revert();
      		if(msg.value < minimumBuyIn*buyInSharePrice) revert();

     		uint256 value = (msg.value/syndicatePrecision)*syndicatePrecision; // ensure precision
		    uint256 allocation = value/buyInSharePrice;

		    if (allocation >= availableBuyInShares){
		        allocation = availableBuyInShares; // limit hit
		    }
		    availableBuyInShares-=allocation;
		    addMember(); // possibly add this member to the syndicate
	      members[msg.sender].numShares+=allocation;

    }

    // how many shares?
    function memberShareCount() public  view returns (uint256) {
        return members[msg.sender].numShares;
    }

    // how much profit?
    function memberProfitShare() public  view returns (uint256) {
        return members[msg.sender].profitShare;
    }

}
/**
 * @title Syndicate
 * @dev Syndicated profit sharing - for early adopters
 * Shares are not transferable -
 */
function buyIntoSyndicate() public payable  {
		if(msg.value==0 || availableBuyInShares==0) revert();
  		if(msg.value < minimumBuyIn*buyInSharePrice) revert();

 		uint256 value = (msg.value/syndicatePrecision)*syndicatePrecision; // ensure precision
  uint256 allocation = value/buyInSharePrice;

  if (allocation >= availableBuyInShares){
      allocation = availableBuyInShares; // limit hit
  }
  availableBuyInShares-=allocation;
  addMember(); // possibly add this member to the syndicate
   members[msg.sender].numShares+=allocation;

}

// buy into syndicate