package cn.ibizlab.codegen.config;

import cn.ibizlab.codegen.utils.OptionUtils;
import org.apache.commons.lang3.tuple.Pair;

import java.util.*;

/**
 * Contains shared logic for applying key-value pairs and CSV strings
 * to specific settings in CodegenConfigurator.
 *
 * <p>
 *     This class exists to facilitate testing. These methods could be applied
 *     to CodegenConfigurator, but this complicates things when mocking CodegenConfigurator.
 * </p>
 * <ul>
 *     <li>The methods named {@code apply...Kvp} take a string of comma-separated key-value pairs.</li>
 *     <li>The methods named {@code apply...KvpList} take a list of such strings.</li>
 *     <li>The method named {@code apply...Csv} takes a string of comma-separated values.</li>
 *     <li>The method named {@code apply...CsvList} takes a list of such strings.</li>
 * </ul>
 * <p>
 *     The corresponding {@code add...} method on the passed configurator is called for each key-value pair (or value).
 * </p>
 */
public final class CodegenConfiguratorUtils {

    public static void applyGlobalPropertiesKvpList(List<String> globalProperties, CodegenConfigurator configurator) {
        for(String propString : globalProperties) {
            applyGlobalPropertiesKvp(propString, configurator);
        }
    }

    public static void applyGlobalPropertiesKvp(String globalProperties, CodegenConfigurator configurator) {
        final Map<String, String> map = createMapFromKeyValuePairs(globalProperties);
        for (Map.Entry<String, String> entry : map.entrySet()) {
            configurator.addGlobalProperty(entry.getKey(), entry.getValue().replace(":",","));
        }
    }


    public static void applyAdditionalPropertiesKvpList(List<String> additionalProperties, CodegenConfigurator configurator) {
        for(String propString : additionalProperties) {
            applyAdditionalPropertiesKvp(propString, configurator);
        }
    }

    public static void applyAdditionalPropertiesKvp(String additionalProperties, CodegenConfigurator configurator) {
        final Map<String, String> map = createMapFromKeyValuePairs(additionalProperties);
        for (Map.Entry<String, String> entry : map.entrySet()) {
            configurator.addAdditionalProperty(entry.getKey(), entry.getValue());
        }
    }


    private static Set<String> createSetFromCsvList(String csvProperty) {
        final List<String> values = OptionUtils.splitCommaSeparatedList(csvProperty);
        return new HashSet<String>(values);
    }

    private static Map<String, String> createMapFromKeyValuePairs(String commaSeparatedKVPairs) {
        final List<Pair<String, String>> pairs = OptionUtils.parseCommaSeparatedTuples(commaSeparatedKVPairs);

        Map<String, String> result = new HashMap<String, String>();

        for (Pair<String, String> pair : pairs) {
            result.put(pair.getLeft(), pair.getRight());
        }

        return result;
    }
}
