@SuppressWarnings("unchecked")
	public boolean login() {
		Credentials credentials = model.getCredentials();

		// login via http also for GET requests
		try {
			boolean successful = connection.login(credentials);
			if (!successful) {
				logger.warn("Failed to login via HTTP.");
			} else {
				logger.info("Successfully logged in via HTTP to " + credentials.getUsername() + ".");
			}
		} catch (IOException e) {
			logger.warn("Failed to login via HTTP:", e);
		}


		Query login = new Query.Builder("login_login", apiVersion, apiClientId, apiAccessToken, secret, apiKey)
				.parameter("vb_login_username", credentials.getUsername())
				.parameter("vb_login_password", credentials.getPassword())
				.parameter("logintype", "modcplogin")
				.parameter("debug", "1")
				.build();

		JsonObject jsonObject;
		try {
			jsonObject = login.run(connection);
		} catch (IOException e) {
			logger.warn("Failed to login:", e);
			return false;
		}

		try {
			// $return['response']['errormessage'] is an array.
			// Its first item is always an error ID (underlying it's actually the error message phrase name).
			// Other items are params coupled with the error.
			JsonObject response = jsonObject.getAsJsonObject("response");
			JsonArray errorMessage = response.get("errormessage").getAsJsonArray();
			String errorId = errorMessage.get(0).getAsString();

			switch (errorId) {
				case "redirect_login":
					String username = errorMessage.get(1).getAsString();
					JsonObject session = jsonObject.getAsJsonObject("session");
					double userId = session.get("userid").getAsInt();
					ForumMember member = new ForumMember((int) userId, username);
					logger.info("Successfully logged into " + member + ".");
					return true;
				case "badlogin":  // called if ($vbulletin->GPC['vb_login_username'] == '')
					logger.warn("Failed to login as the provided user credentials were invalid.");
					return false;
				case "strikes":  // called if ($strikes['strikes'] >= 5 AND $strikes['lasttime'] > TIMENOW - 900)
					logger.warn("Failed to login as we have entered invalid credentials more than 5 times in 15 minutes.");
					return false;
				case "badlogin_strikes_passthru":  // called if $vbulletin->options['usestrikesystem'] is true
					int loginFailedTimes = errorMessage.get(3).getAsInt();
					logger.warn("Failed to login due to invalid user credentials. We have attempted to login " + loginFailedTimes + " times recently.");
					return false;
				case "badlogin_passthru":
					logger.warn("Failed to login due to invalid user credentials.");
					return false;
				default:
					logger.warn("Failed to login.");
					return false;
			}
		} catch (NullPointerException | UnsupportedOperationException e) {
			logger.warn("Failed to login:", e);
			return false;
		}
	}