contract WhitelistableToken is ReleasableToken {
  /**
   * A pre-release list of investors
   */
  struct WhitelistedInvestor {
    uint idx;
    bool whitelisted;
  }

  mapping(address => WhitelistedInvestor) whitelist;

  mapping(uint => address) indexedWhitelist;
  uint whitelistTotal;
  address public whitelistAgent; // Address responsible for adding investors to the whitelist.


  modifier isWhitelisted(address _destination) {
    if(!released) {
      if(!whitelist[_destination].whitelisted) {
        revert();
      }
    }
    _;
  }

  modifier onlyWhitelistAgent(address _sender) {
    if(_sender != whitelistAgent) {
      revert();
    }

    _;
  }

  function isOnWhitelist(address _investor) public view returns (bool whitelisted) {
    return whitelist[_investor].whitelisted;
  }

  function addToWhitelist(address _investor) public onlyWhitelistAgent(msg.sender) {
    if (!whitelist[_investor].whitelisted) { // Should be idempotent to keep duplicates out
      whitelist[_investor].whitelisted = true;
      whitelist[_investor].idx = whitelistTotal;
      indexedWhitelist[whitelistTotal] = _investor;
      whitelistTotal += 1;
    }
  }

  function removeFromWhitelist(address _investor) public onlyWhitelistAgent(msg.sender) {
    if (!whitelist[_investor].whitelisted) {
      revert();
    }
    whitelist[_investor].whitelisted = false;
    uint idx = whitelist[_investor].idx;
    indexedWhitelist[idx] = address(0);
  }

  function setWhitelistAgent(address agent) public onlyOwner {
    whitelistAgent = agent;
  }

  /**
   * Used for iteration.
   */
  function getWhitelistTotal() public view returns (uint total) {
    return whitelistTotal;
  }

  function getWhitelistAt(uint idx) public view returns (address investor) {
    return indexedWhitelist[idx];
  }

  function transfer(address _to, uint _value) isWhitelisted(_to) public returns (bool success) {
    return super.transfer(_to, _value);
  }

  function transferFrom(address _from, address _to, uint256 _value) isWhitelisted(_from) isWhitelisted(_to) public returns (bool) {
    return super.transferFrom(_from, _to, _value);
  }
}
function getWhitelistTotal() public view returns (uint total) {
  return whitelistTotal;
}

/**
 * Used for iteration.
 */