package com.blackducksoftware.integration.hub.dataservices.extension;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.blackducksoftware.integration.hub.api.ExtensionRestService;
import com.blackducksoftware.integration.hub.api.extension.ConfigurationItem;
import com.blackducksoftware.integration.hub.api.user.UserItem;
import com.blackducksoftware.integration.hub.api.user.UserRestService;
import com.blackducksoftware.integration.hub.dataservices.AbstractDataService;
import com.blackducksoftware.integration.hub.dataservices.extension.items.UserConfigItem;
import com.blackducksoftware.integration.hub.exception.BDRestException;
import com.blackducksoftware.integration.hub.exception.MissingUUIDException;
import com.blackducksoftware.integration.hub.logging.IntLogger;
import com.blackducksoftware.integration.hub.rest.RestConnection;
import com.google.gson.Gson;
import com.google.gson.JsonParser;

public class ExtensionConfigDataService extends AbstractDataService {
	private final IntLogger logger;
	private final UserRestService userService;
	private final ExtensionRestService extensionRestService;

	public ExtensionConfigDataService(final IntLogger logger, final RestConnection restConnection, final Gson gson,
			final JsonParser jsonParser, final UserRestService userRestService,
			final ExtensionRestService extensionRestService) {
		super(restConnection, gson, jsonParser);
		this.logger = logger;
		this.userService = userRestService;
		this.extensionRestService = extensionRestService;
	}

	public Map<String, ConfigurationItem> getGlobalConfigMap(final String extensionId) {
		Map<String, ConfigurationItem> globalConfigMap = new HashMap<>();
		try {
			globalConfigMap = createGlobalConfigMap(extensionId);
		} catch (IOException | URISyntaxException | BDRestException e) {
			logger.error("Error creating global configurationMap", e);
		}
		return globalConfigMap;
	}

	public List<UserConfigItem> getUserConfigList(final String extensionId) {
		List<UserConfigItem> itemList = new LinkedList<>();
		try {
			final List<UserItem> userList = userService.getAllUsers();
			itemList = createUserConfigItemList(extensionId, userList);
		} catch (URISyntaxException | BDRestException | IOException | MissingUUIDException e) {
			logger.error("Error creating user configuration", e);
		}

		return itemList;
	}

	public List<UserConfigItem> getUserOverrideConfigList(final String extensionId) {
		List<UserConfigItem> itemList = new LinkedList<>();
		try {
			final List<UserItem> userList = userService.getAllUsers();
			final Map<String, ConfigurationItem> globalConfigMap = createGlobalConfigMap(extensionId);
			itemList = createUserConfigItemList(extensionId, userList);

			for (final UserConfigItem configItem : itemList) {
				final Map<String, ConfigurationItem> userConfigMap = configItem.getConfigMap();
				if (userConfigMap == null || userConfigMap.isEmpty()) {
					userConfigMap.putAll(globalConfigMap);
				} else {
					for (final Map.Entry<String, ConfigurationItem> entry : globalConfigMap.entrySet()) {
						if (!userConfigMap.containsKey(entry.getKey())) {
							userConfigMap.put(entry.getKey(), entry.getValue());
						} else {
							final ConfigurationItem userItem = userConfigMap.get(entry.getKey());
							if (userItem.getValue() == null && userItem.getValue().isEmpty()) {
								userConfigMap.put(entry.getKey(), entry.getValue());
							}
						}
					}
				}
			}

		} catch (URISyntaxException | BDRestException | IOException | MissingUUIDException e) {
			logger.error("Error creating user configuration", e);
		}

		return itemList;
	}

	private Map<String, ConfigurationItem> createGlobalConfigMap(final String extensionId)
			throws IOException, URISyntaxException, BDRestException {
		final List<ConfigurationItem> itemList = extensionRestService.getGlobalOptions(extensionId);
		final Map<String, ConfigurationItem> itemMap = createConfigMap(itemList);
		return itemMap;
	}

	private List<UserConfigItem> createUserConfigItemList(final String extensionId, final List<UserItem> userList)
			throws IOException, URISyntaxException, BDRestException, MissingUUIDException {
		final List<UserConfigItem> itemList = new ArrayList<>(userList.size());
		for (final UserItem user : userList) {
			if (user.isActive()) { // only get active users extension config
				final Map<String, ConfigurationItem> configItems = getUserConfigOptions(extensionId, user);
				itemList.add(new UserConfigItem(user, configItems));
			}
		}
		return itemList;
	}

	private Map<String, ConfigurationItem> getUserConfigOptions(final String extensionId, final UserItem user)
			throws IOException, URISyntaxException, BDRestException, MissingUUIDException {
		// get user ID
		final String userId = user.getUserId().toString();
		final List<ConfigurationItem> userItemList = extensionRestService.getUserConfiguration(extensionId, userId);
		final Map<String, ConfigurationItem> itemMap = createConfigMap(userItemList);

		return itemMap;
	}

	private Map<String, ConfigurationItem> createConfigMap(final List<ConfigurationItem> itemList) {
		final Map<String, ConfigurationItem> itemMap = new HashMap<>(itemList.size());
		for (final ConfigurationItem item : itemList) {
			itemMap.put(item.getName(), item);
		}
		return itemMap;
	}
}

@@ -2482,1274 +2482,8 @@
 %09%7D%0A%0A
-%09public List%3CUserConfigItem%3E getUserOverrideConfigList(final String extensionId) %7B%0A%09%09List%3CUserConfigItem%3E itemList = new LinkedList%3C%3E();%0A%09%09try %7B%0A%09%09%09final List%3CUserItem%3E userList = userService.getAllUsers();%0A%09%09%09final Map%3CString, ConfigurationItem%3E globalConfigMap = createGlobalConfigMap(extensionId);%0A%09%09%09itemList = createUserConfigItemList(extensionId, userList);%0A%0A%09%09%09for (final UserConfigItem configItem : itemList) %7B%0A%09%09%09%09final Map%3CString, ConfigurationItem%3E userConfigMap = configItem.getConfigMap();%0A%09%09%09%09if (userConfigMap == null %7C%7C userConfigMap.isEmpty()) %7B%0A%09%09%09%09%09userConfigMap.putAll(globalConfigMap);%0A%09%09%09%09%7D else %7B%0A%09%09%09%09%09for (final Map.Entry%3CString, ConfigurationItem%3E entry : globalConfigMap.entrySet()) %7B%0A%09%09%09%09%09%09if (!userConfigMap.containsKey(entry.getKey())) %7B%0A%09%09%09%09%09%09%09userConfigMap.put(entry.getKey(), entry.getValue());%0A%09%09%09%09%09%09%7D else %7B%0A%09%09%09%09%09%09%09final ConfigurationItem userItem = userConfigMap.get(entry.getKey());%0A%09%09%09%09%09%09%09if (userItem.getValue() == null && userItem.getValue().isEmpty()) %7B%0A%09%09%09%09%09%09%09%09userConfigMap.put(entry.getKey(), entry.getValue());%0A%09%09%09%09%09%09%09%7D%0A%09%09%09%09%09%09%7D%0A%09%09%09%09%09%7D%0A%09%09%09%09%7D%0A%09%09%09%7D%0A%0A%09%09%7D catch (URISyntaxException %7C BDRestException %7C IOException %7C MissingUUIDException e) %7B%0A%09%09%09logger.error(%22Error creating user configuration%22, e);%0A%09%09%7D%0A%0A%09%09return itemList;%0A%09%7D%0A%0A
 %09pri

Remove the method to override global config with user config