contract RestrictedToken is BasicToken, Ownable {
  string public name;
  string public symbol;
  uint8 public decimals;

  // Authorized senders are able to transfer tokens freely, usu. Sale contract
  address public issuer;

  // Vesting period for exchanging of RestrictedToken to non-restricted token
  // This is for reference by exchange contract and no inherit use for this contract
  uint256 public vestingPeriod;

  // Holders of RestrictedToken are only able to transfer token to authorizedRecipients, usu. Exchange contract
  mapping(address => bool) public authorizedRecipients;

  // Whether recipients are ERC223-compliant
  mapping(address => bool) public erc223Recipients;

  // Last issued time of token per recipient
  mapping(address => uint256) public lastIssuedTime;

  event Issue(address indexed to, uint256 value);

  /**
   * @dev Throws if called by any account other than the issuer.
   */
  modifier onlyIssuer() {
    require(msg.sender == issuer);
    _;
  }

  /**
   * @dev Modifier to check if a transfer is allowed
   */
  modifier isAuthorizedRecipient(address _recipient) {
    require(authorizedRecipients[_recipient]);
    _;
  }

  constructor (
    uint256 _supply,
    string _name,
    string _symbol,
    uint8 _decimals,
    uint256 _vestingPeriod,
    address _owner, // usu. human
    address _issuer // usu. sale contract
  ) public {
    require(_supply != 0);
    require(_owner != address(0));
    require(_issuer != address(0));

    name = _name;
    symbol = _symbol;
    decimals = _decimals;
    vestingPeriod = _vestingPeriod;
    owner = _owner;
    issuer = _issuer;
    totalSupply_ = _supply;
    balances[_issuer] = _supply;
    emit Transfer(address(0), _issuer, _supply);
  }

  /**
   * @dev Allows owner to authorize or deauthorize recipients
   */
  function authorize(address _recipient, bool _isERC223) public onlyOwner {
    require(_recipient != address(0));
    authorizedRecipients[_recipient] = true;
    erc223Recipients[_recipient] = _isERC223;
  }

  function deauthorize(address _recipient) public onlyOwner isAuthorizedRecipient(_recipient) {
    authorizedRecipients[_recipient] = false;
    erc223Recipients[_recipient] = false;
  }

  /**
   * @dev Only allow transfer to authorized recipients
   */
  function transfer(address _to, uint256 _value) public isAuthorizedRecipient(_to) returns (bool) {
    if (erc223Recipients[_to]) {
      BasicERC223Receiver receiver = BasicERC223Receiver(_to);
      bytes memory empty;
      receiver.tokenFallback(msg.sender, _value, empty);
    }
    return super.transfer(_to, _value);
  }

  /**
   * Issue token
   * @dev also records the token issued time
   */
  function issue(address _to, uint256 _value) public onlyIssuer returns (bool) {
    lastIssuedTime[_to] = block.timestamp;

    emit Issue(_to, _value);
    return super.transfer(_to, _value);
  }
}
/**
 * @title RestrictedToken
 * @dev Standard Mintable ERC20 Token that can only be sent to an authorized address
 * Based on Consensys' TokenFoundry's ControllableToken
 * @author U-Zyn Chua <uzyn@zynesis.com>
 */
function authorize(address _recipient, bool _isERC223) public onlyOwner {
  require(_recipient != address(0));
  authorizedRecipients[_recipient] = true;
  erc223Recipients[_recipient] = _isERC223;
}

/**
 * @dev Allows owner to authorize or deauthorize recipients
 */