class SetAttribute implements Runnable {

    @Override
    public void run() {
        Optional<Client> possibleClient = manager.getClientByID(uid);
        if (!possibleClient.isPresent()) {
            outputStream.println("No client exists with that user ID");
            return;
        }

        Client client = possibleClient.get();

        if (!RegionValidator.isValid(country == null ? client.getCountry() : country, region)) {
            outputStream.printf("%s is not a valid NZ region%n", region);
            return;
        }

        ModifyClientAction action = new ModifyClientAction(client, manager);

        Map<String, Object[]> states = new HashMap<>();
        states.put("firstName", new String[]{client.getFirstName(), firstName});
        states.put("middleName", new String[]{client.getMiddleName(), middleName});
        states.put("lastName", new String[]{client.getLastName(), lastName});
        states.put("currentAddress", new String[]{client.getCurrentAddress(), address});
        states.put("region", new String[]{client.getRegion(), region});
        states.put("country", new Country[]{client.getCountry(), country});
        states.put("gender", new Gender[]{client.getGender(), gender});
        states.put("bloodType", new BloodType[]{client.getBloodType(), bloodType});
        states.put("height", new Double[]{client.getHeight(), height});
        states.put("weight", new Double[]{client.getWeight(), weight});
        states.put("dateOfBirth", new LocalDate[]{client.getDateOfBirth(), dateOfBirth});
        states.put("dateOfDeath", new LocalDate[]{client.getDateOfDeath(), dateOfDeath});

        for (Entry<String, Object[]> entry : states.entrySet()) {
            if (entry.getValue()[1] == null) {
                continue;
            }
            try {
                action.addChange(entry.getKey(), entry.getValue()[0], entry.getValue()[1]);
            } catch (NoSuchFieldException e) {
                LOGGER.log(Level.WARNING, e.getMessage(), e);
            }
        }

        outputStream.println(invoker.execute(action));
    }

    public  SetAttribute(PrintStream outputStream, ActionInvoker invoker);
    public  SetAttribute(ClientManager manager, ActionInvoker invoker);

}