// © 2019 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
package org.unicode.icu.tool.cldrtoicu;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.unicode.cldr.api.CldrDataSupplier.CldrResolution.RESOLVED;
import static org.unicode.cldr.api.CldrDataSupplier.CldrResolution.UNRESOLVED;
import static org.unicode.cldr.api.CldrDataType.BCP47;
import static org.unicode.cldr.api.CldrDataType.LDML;
import static org.unicode.cldr.api.CldrDataType.SUPPLEMENTAL;
import static org.unicode.icu.tool.cldrtoicu.LdmlConverterConfig.IcuLocaleDir.BRKITR;
import static org.unicode.icu.tool.cldrtoicu.LdmlConverterConfig.IcuLocaleDir.COLL;
import static org.unicode.icu.tool.cldrtoicu.LdmlConverterConfig.IcuLocaleDir.CURR;
import static org.unicode.icu.tool.cldrtoicu.LdmlConverterConfig.IcuLocaleDir.LANG;
import static org.unicode.icu.tool.cldrtoicu.LdmlConverterConfig.IcuLocaleDir.LOCALES;
import static org.unicode.icu.tool.cldrtoicu.LdmlConverterConfig.IcuLocaleDir.RBNF;
import static org.unicode.icu.tool.cldrtoicu.LdmlConverterConfig.IcuLocaleDir.REGION;
import static org.unicode.icu.tool.cldrtoicu.LdmlConverterConfig.IcuLocaleDir.UNIT;
import static org.unicode.icu.tool.cldrtoicu.LdmlConverterConfig.IcuLocaleDir.ZONE;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.unicode.cldr.api.CldrData;
import org.unicode.cldr.api.CldrDataSupplier;
import org.unicode.cldr.api.CldrDataType;
import org.unicode.cldr.api.CldrPath;
import org.unicode.cldr.api.PathMatcher;
import org.unicode.icu.tool.cldrtoicu.LdmlConverterConfig.IcuLocaleDir;
import org.unicode.icu.tool.cldrtoicu.LdmlConverterConfig.IcuVersionInfo;
import org.unicode.icu.tool.cldrtoicu.localedistance.LocaleDistanceMapper;
import org.unicode.icu.tool.cldrtoicu.mapper.Bcp47Mapper;
import org.unicode.icu.tool.cldrtoicu.mapper.BreakIteratorMapper;
import org.unicode.icu.tool.cldrtoicu.mapper.CollationMapper;
import org.unicode.icu.tool.cldrtoicu.mapper.DayPeriodsMapper;
import org.unicode.icu.tool.cldrtoicu.mapper.LocaleMapper;
import org.unicode.icu.tool.cldrtoicu.mapper.PluralRangesMapper;
import org.unicode.icu.tool.cldrtoicu.mapper.PluralsMapper;
import org.unicode.icu.tool.cldrtoicu.mapper.RbnfMapper;
import org.unicode.icu.tool.cldrtoicu.mapper.SupplementalMapper;
import org.unicode.icu.tool.cldrtoicu.mapper.TransformsMapper;
import org.unicode.icu.tool.cldrtoicu.regex.RegexTransformer;

import com.google.common.base.CharMatcher;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import com.google.common.io.CharStreams;

/**
 * The main converter tool for CLDR to ICU data. To run this tool, you need to supply a suitable
 * {@link LdmlConverterConfig} instance. There is a simple {@code main()} method available in this
 * class which can be invoked passing just the desired output directory and which relies on the
 * presence of several system properties for the remainder of its parameters:
 * <ul>
 *     <li>CLDR_DIR: The root of the CLDR release from which CLDR data is read.
 *     <li>ICU_DIR: The root of the ICU release from which additional "specials" XML data is read.
 *     <li>CLDR_DTD_CACHE: A temporary directory with the various DTDs cached (this is a legacy
 *         requirement from the underlying CLDR libraries and might go away one day).
 * </ul>
 */
public final class LdmlConverter {
    // TODO: Do all supplemental data in one go and split similarly to locale data (using RbPath).
    private static final Predicate<CldrPath> GENDER_LIST_PATHS =
        supplementalMatcher("gender");
    private static final Predicate<CldrPath> LIKELY_SUBTAGS_PATHS =
        supplementalMatcher("likelySubtags");
    private static final Predicate<CldrPath> METAZONE_PATHS =
        supplementalMatcher("metaZones", "primaryZones");
    private static final Predicate<CldrPath> METADATA_PATHS =
        supplementalMatcher("metadata");
    private static final Predicate<CldrPath> SUPPLEMENTAL_DATA_PATHS =
        supplementalMatcher(
            "calendarData",
            "calendarPreferenceData",
            "codeMappings",
            "codeMappingsCurrency",
            "idValidity",
            "languageData",
            "languageMatching",
            "measurementData",
            "parentLocales",
            "subdivisionContainment",
            "territoryContainment",
            "territoryInfo",
            "timeData",
            "weekData",
            "weekOfPreference");
    private static final Predicate<CldrPath> CURRENCY_DATA_PATHS =
        supplementalMatcher("currencyData");
    private static final Predicate<CldrPath> UNITS_DATA_PATHS =
        supplementalMatcher(
            "convertUnits",
            "unitConstants",
            "unitQuantities",
            "unitPreferenceData");
    private static final Predicate<CldrPath> GRAMMATICAL_FEATURES_PATHS =
        supplementalMatcher("grammaticalData");
    private static final Predicate<CldrPath> NUMBERING_SYSTEMS_PATHS =
        supplementalMatcher("numberingSystems");
    private static final Predicate<CldrPath> WINDOWS_ZONES_PATHS =
        supplementalMatcher("windowsZones");

    private static Predicate<CldrPath> supplementalMatcher(String... spec) {
        checkArgument(spec.length > 0, "must supply at least one matcher spec");
        if (spec.length == 1) {
            return PathMatcher.of("//supplementalData/" + spec[0])::matchesPrefixOf;
        }
        return
            Arrays.stream(spec)
                .map(s -> PathMatcher.of("//supplementalData/" + s))
                .map(m -> ((Predicate<CldrPath>) m::matchesPrefixOf))
                .reduce(p -> false, Predicate::or);
    }

    private static RbPath RB_PARENT = RbPath.of("%%Parent");
    // The quotes below are only so we achieve parity with the manually written alias files.
    // TODO: Remove unnecessary quotes once the migration to this code is complete.
    private static RbPath RB_ALIAS = RbPath.of("\"%%ALIAS\"");
    // Special path for adding to empty files which only exist to complete the parent chain.
    // TODO: Confirm that this has no meaningful effect and unify "empty" file contents.
    private static RbPath RB_EMPTY_ALIAS = RbPath.of("___");

    /**
     * Output types defining specific subsets of the ICU data which can be converted separately.
     * This closely mimics the original "NewLdml2IcuConverter" behaviour but could be simplified to
     * hide what are essentially implementation specific data splits.
     */
    public enum OutputType {
        LOCALES(LDML),
        BRKITR(LDML),
        COLL(LDML),
        RBNF(LDML),
        DAY_PERIODS(SUPPLEMENTAL),
        GENDER_LIST(SUPPLEMENTAL),
        LIKELY_SUBTAGS(SUPPLEMENTAL),
        SUPPLEMENTAL_DATA(SUPPLEMENTAL),
        UNITS(SUPPLEMENTAL),
        CURRENCY_DATA(SUPPLEMENTAL),
        GRAMMATICAL_FEATURES(SUPPLEMENTAL),
        METADATA(SUPPLEMENTAL),
        META_ZONES(SUPPLEMENTAL),
        NUMBERING_SYSTEMS(SUPPLEMENTAL),
        PLURALS(SUPPLEMENTAL),
        PLURAL_RANGES(SUPPLEMENTAL),
        WINDOWS_ZONES(SUPPLEMENTAL),
        TRANSFORMS(SUPPLEMENTAL),
        LOCALE_DISTANCE(SUPPLEMENTAL),
        VERSION(SUPPLEMENTAL),
        KEY_TYPE_DATA(BCP47);

        public static final ImmutableSet<OutputType> ALL = ImmutableSet.copyOf(OutputType.values());

        private final CldrDataType type;

        OutputType(CldrDataType type) {
            this.type = checkNotNull(type);
        }

        CldrDataType getCldrType() {
            return type;
        }
    }

    // Map to convert the rather arbitrarily defined "output types" to the directories into which
    // the data is written. This is only for "LDML" types since other mappers don't need to split
    // data into multiple directories.
    private static final ImmutableListMultimap<OutputType, IcuLocaleDir> TYPE_TO_DIR =
        ImmutableListMultimap.<OutputType, IcuLocaleDir>builder()
            .putAll(OutputType.LOCALES, CURR, LANG, LOCALES, REGION, UNIT, ZONE)
            .putAll(OutputType.BRKITR, BRKITR)
            .putAll(OutputType.COLL, COLL)
            .putAll(OutputType.RBNF, RBNF)
            .build();

    /** Converts CLDR data according to the given configuration. */
    public static void convert(
        CldrDataSupplier src, SupplementalData supplementalData, LdmlConverterConfig config) {
        new LdmlConverter(src, supplementalData, config).convertAll();
    }

    // The supplier for all data to be converted.
    private final CldrDataSupplier src;
    // Supplemental data available to mappers if needed.
    private final SupplementalData supplementalData;
    // The configuration controlling conversion behaviour.
    private final LdmlConverterConfig config;
    // The set of expanded target locale IDs.
    // TODO: Make available IDs include specials files (or fail if specials are not available).
    private final ImmutableSet<String> availableIds;
    // Transformer for locale data.
    private final PathValueTransformer localeTransformer;
    // Transformer for supplemental data.
    private final PathValueTransformer supplementalTransformer;
    // Header string to go into every ICU data and transliteration rule file (comment prefixes
    // are not present and must be added by the code writing the file).
    private final ImmutableList<String> fileHeader;

    private LdmlConverter(
        CldrDataSupplier src, SupplementalData supplementalData, LdmlConverterConfig config) {
        this.src = checkNotNull(src);
        this.supplementalData = checkNotNull(supplementalData);
        this.config = checkNotNull(config);
        this.availableIds = ImmutableSet.copyOf(
            Sets.intersection(supplementalData.getAvailableLocaleIds(), config.getAllLocaleIds()));
        // Load the remaining path value transformers.
        this.supplementalTransformer =
            RegexTransformer.fromConfigLines(readLinesFromResource("/ldml2icu_supplemental.txt"),
                IcuFunctions.ALGORITHM_FN,
                IcuFunctions.DATE_FN,
                IcuFunctions.DAY_NUMBER_FN,
                IcuFunctions.EXP_FN,
                IcuFunctions.YMD_FN);
        this.localeTransformer =
            RegexTransformer.fromConfigLines(readLinesFromResource("/ldml2icu_locale.txt"),
                IcuFunctions.CONTEXT_TRANSFORM_INDEX_FN);
        this.fileHeader = readLinesFromResource("/ldml2icu_header.txt");
    }

    private void convertAll() {
        processLdml();
        processSupplemental();
        if (config.emitReport()) {
            System.out.println("Supplemental Data Transformer=" + supplementalTransformer);
            System.out.println("Locale Data Transformer=" + localeTransformer);
        }
    }

    private static ImmutableList<String> readLinesFromResource(String name) {
        try (InputStream in = LdmlConverter.class.getResourceAsStream(name)) {
            return ImmutableList.copyOf(CharStreams.readLines(new InputStreamReader(in, UTF_8)));
        } catch (IOException e) {
            throw new RuntimeException("cannot read resource: " + name, e);
        }
    }

    private Optional<CldrData> loadSpecialsData(String localeId) {
        String expected = localeId + ".xml";
        try (Stream<Path> files = Files.walk(config.getSpecialsDir())) {
            Set<Path> xmlFiles = files
                .filter(Files::isRegularFile)
                .filter(f -> f.getFileName().toString().equals(expected))
                .collect(Collectors.toSet());
            return !xmlFiles.isEmpty()
                ? Optional.of(
                CldrDataSupplier.forCldrFiles(LDML, config.getMinimumDraftStatus(), xmlFiles))
                : Optional.empty();
        } catch (IOException e) {
            throw new RuntimeException(
                "error processing specials directory: " + config.getSpecialsDir(), e);
        }
    }

    private void processLdml() {
        ImmutableList<IcuLocaleDir> splitDirs =
            config.getOutputTypes().stream()
                .filter(t -> t.getCldrType() == LDML)
                .flatMap(t -> TYPE_TO_DIR.get(t).stream())
                .collect(toImmutableList());
        if (splitDirs.isEmpty()) {
            return;
        }

        String cldrVersion = config.getVersionInfo().getCldrVersion();

        Map<IcuLocaleDir, DependencyGraph> graphMetadata = new HashMap<>();
        splitDirs.forEach(d -> graphMetadata.put(d, new DependencyGraph(cldrVersion)));

        SetMultimap<IcuLocaleDir, String> writtenLocaleIds = HashMultimap.create();
        Path baseDir = config.getOutputDir();

        for (String id : config.getAllLocaleIds()) {
            // Skip "target" IDs that are aliases (they are handled later).
            if (!availableIds.contains(id)) {
                continue;
            }
            // TODO: Remove the following skip when ICU-20997 is fixed
            if (id.contains("VALENCIA")) {
                System.out.println("(skipping " + id + " until ICU-20997 is fixed)");
                continue;
            }

            IcuData icuData = new IcuData(id, true);

            Optional<CldrData> specials = loadSpecialsData(id);
            CldrData unresolved = src.getDataForLocale(id, UNRESOLVED);

            BreakIteratorMapper.process(icuData, unresolved, specials);
            CollationMapper.process(icuData, unresolved, specials, cldrVersion);
            RbnfMapper.process(icuData, unresolved, specials);

            CldrData resolved = src.getDataForLocale(id, RESOLVED);
            Optional<String> defaultCalendar = supplementalData.getDefaultCalendar(id);
            LocaleMapper.process(
                icuData, unresolved, resolved, specials, localeTransformer, defaultCalendar);

            ListMultimap<IcuLocaleDir, RbPath> splitPaths = LinkedListMultimap.create();
            for (RbPath p : icuData.getPaths()) {
                String rootName = getBaseSegmentName(p.getSegment(0));
                splitPaths.put(LOCALE_SPLIT_INFO.getOrDefault(rootName, LOCALES), p);
            }

            Optional<String> parent = supplementalData.getExplicitParentLocaleOf(id);
            // We always write base languages (even if empty).
            boolean isBaseLanguage = !id.contains("_");
            // Run through all directories (not just the keySet() of the split path map) since we
            // sometimes write empty files.
            for (IcuLocaleDir dir : splitDirs) {
                Set<String> targetIds = config.getTargetLocaleIds(dir);
                if (!targetIds.contains(id)) {
                    if (!splitPaths.get(dir).isEmpty()) {
                        System.out.format(
                            "target IDs for %s does not contain %s, but it has data: %s\n",
                            dir, id, splitPaths.get(dir));
                    }
                    continue;
                }

                Path outDir = baseDir.resolve(dir.getOutputDir());
                IcuData splitData = new IcuData(icuData.getName(), icuData.hasFallback());

                // The split data can still be empty for this directory, but that's expected (it
                // might only be written because it has an explicit parent added below).
                splitPaths.get(dir).forEach(p -> splitData.add(p, icuData.get(p)));

                // If we add an explicit parent locale, it forces the data to be written. This is
                // where we check for forced overrides of the parent relationship (which is a per
                // directory thing).
                getIcuParent(id, parent, dir).ifPresent(p -> {
                    splitData.add(RB_PARENT, p);
                    graphMetadata.get(dir).addParent(id, p);
                });

                if (!splitData.getPaths().isEmpty() || isBaseLanguage || dir.includeEmpty()) {
                    if (id.equals("root")) {
                        splitData.setVersion(cldrVersion);
                    }
                    write(splitData, outDir, false);
                    writtenLocaleIds.put(dir, id);
                }
            }
        }

        for (IcuLocaleDir dir : splitDirs) {
            Path outDir = baseDir.resolve(dir.getOutputDir());
            Set<String> targetIds = config.getTargetLocaleIds(dir);
            DependencyGraph depGraph = graphMetadata.get(dir);

            // TODO: Maybe calculate alias map directly into the dependency graph?
            Map<String, String> aliasMap = getAliasMap(targetIds, dir);
            aliasMap.forEach((s, t) -> {
                depGraph.addAlias(s, t);
                writeAliasFile(s, t, outDir);
                // It's only important to record which alias files are written because of forced
                // aliases, but since it's harmless otherwise, we just do it unconditionally.
                // Normal alias files don't affect the empty file calculation, but forced ones can.
                writtenLocaleIds.put(dir, s);
            });

            calculateEmptyFiles(writtenLocaleIds.get(dir), aliasMap.values())
                .forEach(id -> writeEmptyFile(id, outDir, aliasMap.values()));

            writeDependencyGraph(outDir, depGraph);
        }
    }


    private static final CharMatcher PATH_MODIFIER = CharMatcher.anyOf(":%");

    // Resource bundle paths elements can have variants (e.g. "Currencies%narrow) or type
    // annotations (e.g. "languages:intvector"). We strip these when considering the element name.
    private static String getBaseSegmentName(String segment) {
        int idx = PATH_MODIFIER.indexIn(segment);
        return idx == -1 ? segment : segment.substring(0, idx);
    }

    /*
     * There are four reasons for treating a locale ID as an alias.
     * 1: It contains deprecated subtags (e.g. "sr_YU", which should be "sr_Cyrl_RS").
     * 2: It has no CLDR data but is missing a script subtag.
     * 3: It is one of the special "phantom" alias which cannot be represented normally
     *    and must be manually mapped (e.g. legacy locale IDs which don't even parse).
     * 4: It is a "super special" forced alias, which might replace existing aliases in
     *    some output directories.
     */
    private Map<String, String> getAliasMap(Set<String> localeIds, IcuLocaleDir dir) {
        // Even forced aliases only apply if they are in the set of locale IDs for the directory.
        Map<String, String> forcedAliases =
            Maps.filterKeys(config.getForcedAliases(dir), localeIds::contains);

        Map<String, String> aliasMap = new LinkedHashMap<>();
        for (String id : localeIds) {
            if (forcedAliases.containsKey(id)) {
                // Forced aliases will be added later and don't need to be processed here. This
                // is especially necessary if the ID is not structurally valid (e.g. "no_NO_NY")
                // since that cannot be processed by the code below.
                continue;
            }
            String canonicalId = supplementalData.replaceDeprecatedTags(id);
            if (!canonicalId.equals(id)) {
                // If the canonical form of an ID differs from the requested ID, the this is an
                // alias, and just needs to point to the canonical ID.
                aliasMap.put(id, canonicalId);
                continue;
            }
            if (availableIds.contains(id)) {
                // If it's canonical and supported, it's not an alias.
                continue;
            }
            // If the requested locale is not supported, maximize it and alias to that.
            String maximizedId = supplementalData.maximize(id)
                .orElseThrow(() -> new IllegalArgumentException("unsupported locale ID: " + id));
            // We can't alias to ourselves and we shouldn't be here is the ID was already maximal.
            checkArgument(!maximizedId.equals(id), "unsupported maximized locale ID: %s", id);
            aliasMap.put(id, maximizedId);
        }
        // Important that we overwrite entries which might already exist here, since we might have
        // already calculated a "natural" alias for something that we want to force (and we should
        // replace the existing target, since that affects how we determine empty files later).
        aliasMap.putAll(forcedAliases);
        return aliasMap;
    }

    /*
     * Helper to determine the correct parent ID to be written into the ICU data file. The rules
     * are:
     * 1: If no forced parent exists (common) write the explicit parent (if that exists)
     * 2: If a forced parent exists, but the forced value is what you would get by just truncating
     *    the current locale ID, write nothing (ICU libraries truncate when no parent is set).
     * 3: Write the forced parent (this is an exceptional case, and may not even occur in data).
     */
    private Optional<String> getIcuParent(String id, Optional<String> parent, IcuLocaleDir dir) {
        String forcedParentId = config.getForcedParents(dir).get(id);
        if (forcedParentId == null) {
            return parent;
        }
        return id.contains("_") && forcedParentId.regionMatches(0, id, 0, id.lastIndexOf('_'))
            ? Optional.empty() : Optional.of(forcedParentId);
    }

    private void processSupplemental() {
        for (OutputType type : config.getOutputTypes()) {
            if (type.getCldrType() == LDML) {
                continue;
            }
            switch (type) {
            case DAY_PERIODS:
                write(DayPeriodsMapper.process(src), "misc");
                break;

            case GENDER_LIST:
                processSupplemental("genderList", GENDER_LIST_PATHS, "misc", false);
                break;

            case LIKELY_SUBTAGS:
                processSupplemental("likelySubtags", LIKELY_SUBTAGS_PATHS, "misc", false);
                break;

            case SUPPLEMENTAL_DATA:
                processSupplemental("supplementalData", SUPPLEMENTAL_DATA_PATHS, "misc", true);
                break;

            case UNITS:
                processSupplemental("units", UNITS_DATA_PATHS, "misc", true);
                break;

            case CURRENCY_DATA:
                processSupplemental("supplementalData", CURRENCY_DATA_PATHS, "curr", false);
                break;

            case GRAMMATICAL_FEATURES:
                processSupplemental("grammaticalFeatures", GRAMMATICAL_FEATURES_PATHS, "misc", false);

            case METADATA:
                processSupplemental("metadata", METADATA_PATHS, "misc", false);
                break;

            case META_ZONES:
                processSupplemental("metaZones", METAZONE_PATHS, "misc", false);
                break;

            case NUMBERING_SYSTEMS:
                processSupplemental("numberingSystems", NUMBERING_SYSTEMS_PATHS, "misc", false);
                break;

            case PLURALS:
                write(PluralsMapper.process(src), "misc");
                break;

            case PLURAL_RANGES:
                write(PluralRangesMapper.process(src), "misc");
                break;

            case LOCALE_DISTANCE:
                write(LocaleDistanceMapper.process(src), "misc");
                break;

            case WINDOWS_ZONES:
                processSupplemental("windowsZones", WINDOWS_ZONES_PATHS, "misc", false);
                break;

            case TRANSFORMS:
                Path transformDir = createDirectory(config.getOutputDir().resolve("translit"));
                write(TransformsMapper.process(src, transformDir, fileHeader), transformDir, false);
                break;

            case VERSION:
                writeIcuVersionInfo();
                break;

            case KEY_TYPE_DATA:
                Bcp47Mapper.process(src).forEach(d -> write(d, "misc"));
                break;

            default:
                throw new AssertionError("Unsupported supplemental type: " + type);
            }
        }
    }

    private static final RbPath RB_CLDR_VERSION = RbPath.of("cldrVersion");

    private void processSupplemental(
        String label, Predicate<CldrPath> paths, String dir, boolean addCldrVersion) {
        IcuData icuData =
            SupplementalMapper.process(src, supplementalTransformer, label, paths);
        // A hack for "supplementalData.txt" since the "cldrVersion" value doesn't come from the
        // supplemental data XML files.
        if (addCldrVersion) {
            // Not the same path as used by "setVersion()"
            icuData.add(RB_CLDR_VERSION, config.getVersionInfo().getCldrVersion());
        }
        write(icuData, dir);
    }

    private void writeAliasFile(String srcId, String destId, Path dir) {
        IcuData icuData = new IcuData(srcId, true);
        icuData.add(RB_ALIAS, destId);
        // Allow overwrite for aliases since some are "forced" and overwrite existing targets.
        // TODO: Maybe tighten this up so only forced aliases for existing targets are overwritten.
        write(icuData, dir, true);
    }

    private void writeEmptyFile(String id, Path dir, Collection<String> aliasTargets) {
        IcuData icuData = new IcuData(id, true);
        // TODO: Document the reason for this (i.e. why does it matter what goes into empty files?)
        if (aliasTargets.contains(id)) {
            icuData.setFileComment("generated alias target");
            icuData.add(RB_EMPTY_ALIAS, "");
        } else {
            // These empty files only exist because the target of an alias has a parent locale
            // which is itself not in the set of written ICU files. An "indirect alias target".
            // No need to add data: Just write a resource bundle with an empty top-level table.
        }
        write(icuData, dir, false);
    }

    private void writeIcuVersionInfo() {
        IcuVersionInfo versionInfo = config.getVersionInfo();
        IcuData versionData = new IcuData("icuver", false);
        versionData.add(RbPath.of("ICUVersion"), versionInfo.getIcuVersion());
        versionData.add(RbPath.of("DataVersion"), versionInfo.getIcuDataVersion());
        versionData.add(RbPath.of("CLDRVersion"), versionInfo.getCldrVersion());
        // Write file via non-helper methods since we need to include a legacy copyright.
        Path miscDir = config.getOutputDir().resolve("misc");
        createDirectory(miscDir);
        ImmutableList<String> versionHeader = ImmutableList.<String>builder()
            .addAll(fileHeader)
            .add(
                "***************************************************************************",
                "*",
                "* Copyright (C) 2010-2016 International Business Machines",
                "* Corporation and others.  All Rights Reserved.",
                "*",
                "***************************************************************************")
            .build();
        IcuTextWriter.writeToFile(versionData, miscDir, versionHeader, false);
    }

    // Commonest case for writing data files in "normal" directories.
    private void write(IcuData icuData, String dir) {
        write(icuData, config.getOutputDir().resolve(dir), false);
    }

    private void write(IcuData icuData, Path dir, boolean allowOverwrite) {
        createDirectory(dir);
        IcuTextWriter.writeToFile(icuData, dir, fileHeader, allowOverwrite);
    }

    private Path createDirectory(Path dir) {
        try {
            Files.createDirectories(dir);
        } catch (IOException e) {
            throw new RuntimeException("cannot create directory: " + dir, e);
        }
        return dir;
    }

    private void writeDependencyGraph(Path dir, DependencyGraph depGraph) {
        createDirectory(dir);
        try (BufferedWriter w = Files.newBufferedWriter(dir.resolve("LOCALE_DEPS.json"), UTF_8);
            PrintWriter out = new PrintWriter(w)) {
            depGraph.writeJsonTo(out, fileHeader);
            out.flush();
        } catch (IOException e) {
            throw new RuntimeException("cannot write dependency graph file: " + dir, e);
        }
    }

    // The set of IDs to process is:
    // * any file that was written
    // * any alias target (not written)
    //
    // From which we generate the complete "closure" under the "getParent()" function. This set
    // contains all file (written or not) which need to exist to complete the locale hierarchy.
    //
    // Then we remove all the written files to just leave the ones that need to be generated.
    // This is a simple and robust approach that handles things like "gaps" in non-aliased
    // locale IDs, where an intermediate parent is not present.
    private ImmutableSet<String> calculateEmptyFiles(
        Set<String> writtenIds, Collection<String> aliasTargetIds) {

        Set<String> seedIds = new HashSet<>(writtenIds);
        seedIds.addAll(aliasTargetIds);
        // Be nice and sort the output (makes easier debugging).
        Set<String> allIds = new TreeSet<>();
        for (String id : seedIds) {
            while (!id.equals("root") && !allIds.contains(id)) {
                allIds.add(id);
                id = supplementalData.getParent(id);
            }
        }
        return ImmutableSet.copyOf(Sets.difference(allIds, writtenIds));
    }

    private static final ImmutableMap<String, IcuLocaleDir> LOCALE_SPLIT_INFO =
        ImmutableMap.<String, IcuLocaleDir>builder()
            // BRKITR
            .put("boundaries", BRKITR)
            .put("dictionaries", BRKITR)
            .put("exceptions", BRKITR)
            // COLL
            .put("collations", COLL)
            .put("depends", COLL)
            .put("UCARules", COLL)
            // CURR
            .put("Currencies", CURR)
            .put("CurrencyPlurals", CURR)
            .put("CurrencyUnitPatterns", CURR)
            .put("currencySpacing", CURR)
            // LANG
            .put("Keys", LANG)
            .put("Languages", LANG)
            .put("Scripts", LANG)
            .put("Types", LANG)
            .put("Variants", LANG)
            .put("characterLabelPattern", LANG)
            .put("codePatterns", LANG)
            .put("localeDisplayPattern", LANG)
            // RBNF
            .put("RBNFRules", RBNF)
            // REGION
            .put("Countries", REGION)
            // UNIT
            .put("durationUnits", UNIT)
            .put("units", UNIT)
            .put("unitsShort", UNIT)
            .put("unitsNarrow", UNIT)
            // ZONE
            .put("zoneStrings", ZONE)
            .build();
}
