contract Identity is ResolverClient, DigixConstants {

  function Identity(address _resolver) public
  {
    require(init(CONTRACT_INTERACTIVE_IDENTITY, _resolver));
  }

  function identity_controller()
           internal
           constant
           returns (IdentityController _contract)
  {
    _contract = IdentityController(get_contract(CONTRACT_CONTROLLER_IDENTITY));
  }

  function identity_storage()
           internal
           constant
           returns (IdentityStorage _contract)
  {
    _contract = IdentityStorage(get_contract(CONTRACT_STORAGE_IDENTITY));
  }

  function approveKyc(address _caller, address _user, uint256 _id_expiration, uint256 _daily_dgx_ng_limit)
           internal
           returns (bool _success)
  {
    _success = identity_controller().put_user_kyc_approve(_caller, _user, _id_expiration, _daily_dgx_ng_limit);
  }

  /// @dev approve kyc of users in bulk
  /// @param _users addresses of users
  /// @return _success true if successfully approved, throw otherwise
  function bulkApproveKyc(address[] _users, uint256[] _id_expirations, uint256[] _daily_dgx_ng_limits)
           public
           returns (bool _success)
  {
    address _caller = msg.sender;
    uint256 length = _users.length;
    for (uint256 i = 0; i < length; i += 1) {
      require(approveKyc(_caller, _users[i], _id_expirations[i], _daily_dgx_ng_limits[i]));
    }
    _success = true;
  }

  function revokeKyc(address _caller, address _user)
           internal
           returns (bool _success)
  {
    _success = identity_controller().put_user_kyc_revoke(_caller, _user);
  }

  /// @dev revoke kyc of users in bulk
  /// @param _users addresses of users
  /// @return _success true if successfully revoked, throw otherwise
  function bulkRevokeKyc(address[] _users)
           public
           returns (bool _success)
  {
    uint256 length = _users.length;
    address _caller = msg.sender;
    for (uint256 i = 0; i < length; i += 1) {
      require(revokeKyc(_caller, _users[i]));
    }
    _success = true;
  }

  function changeUserDoc(address _caller, address _user, bytes32 _doc)
           internal
           returns (bool _success)
  {
    _success = identity_controller().put_user_doc(_caller, _user, _doc);
  }

  /// @dev change KYC documents of users in bulk
  /// @param _users addresses of users
  /// @param _docs IPFS hashes of KYC documents
  /// @return _success true if docs added successfully, throw otherwise
  function bulkChangeUserDoc(address[] _users, bytes32[] _docs)
           public
           returns (bool _success)
  {
    uint256 length = _users.length;
    address _caller = msg.sender;
    for (uint256 i = 0; i < length; i += 1) {
      require(changeUserDoc(_caller, _users[i], _docs[i]));
    }
    _success = true;
  }

  /// @dev show user KYC information
  /// @param _user address of the user
  /// @return {
  ///   "_id_expiration": "expiry time of the user's KYC status",
  ///   "_doc": "IPFS hash of any information linked to user's KYC"
  /// }
  function showUser(address _user)
           public
           constant
           returns (uint256 _id_expiration, bytes32 _doc)
  {
    (_id_expiration, _doc) = identity_storage().read_user(_user);
  }

  /// @dev check if user KYC is valid
  /// @param _user address of user
  /// @return _valid_kyc true if user has valid KYC, otherwise false
  function checkUserKyc(address _user)
           public
           constant
           returns (bool _valid_kyc)
  {
    _valid_kyc = identity_storage().read_user_kyc_valid(_user);
  }
}
/// @title User KYC information
/// @author Digix Holdings Pte Ltd
/// @notice Use this contract for interactive functions to update to or read information regarding user KYCs
function bulkRevokeKyc(address[] _users)
         public
         returns (bool _success)
{
  uint256 length = _users.length;
  address _caller = msg.sender;
  for (uint256 i = 0; i < length; i += 1) {
    require(revokeKyc(_caller, _users[i]));
  }
  _success = true;
}

/// @dev revoke kyc of users in bulk
/// @param _users addresses of users
/// @return _success true if successfully revoked, throw otherwise