/*
 * Copyright (C) 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.carrier;

import static com.google.common.collect.Multimaps.flatteningToMultimap;
import static com.google.common.collect.Multimaps.toMultimap;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Comparator.comparing;

import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.google.auto.value.AutoValue;
import com.google.common.base.Ascii;
import com.google.common.base.CharMatcher;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import com.google.protobuf.Descriptors;
import com.google.protobuf.TextFormat;
import com.google.carrier.CarrierConfig;
import com.google.carrier.CarrierId;
import com.google.carrier.CarrierList;
import com.google.carrier.CarrierMap;
import com.google.carrier.CarrierSettings;
import com.google.carrier.IntArray;
import com.google.carrier.MultiCarrierSettings;
import com.google.carrier.TextArray;
import com.android.providers.telephony.CarrierIdProto.CarrierAttribute;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * This command converts carrier config XML into text protobuf.
 *
 * <ul>
 *   <li>input: the assets/ from AOSP CarrierConfig app
 *   <li>input: vendor.xml file(s) which override(s) assets
 *   <li>input: a tier-1 carrier list in text protobuf (in --output_dir)
 *   <li>input: the version number for output files
 *   <li>output: an other_carriers.textpb - a list of other (non-tier-1) carriers
 *   <li>output: an others.textpb containing carrier configs for non tier-1 carriers
 *   <li>output: a .textpb for every single tier-1 carrier
 * </ul>
 */
@Parameters(separators = "=")
public final class CarrierConfigConverterV2 {
  @Parameter(names = "--assets", description = "The source AOSP assets/ directory.")
  private String assetsDirName = "/tmp/carrierconfig/assets";

  @Parameter(
      names = "--vendor_xml",
      description =
          "The source vendor.xml file(s). If multiple files provided, the order decides config"
              + " precedence, ie. configs in a file are overwritten by configs in files AFTER it.")
  private List<String> vendorXmlFiles = ImmutableList.of("/tmp/carrierconfig/vendor.xml");

  @Parameter(
      names = "--output_dir",
      description = "The destination data directory, with tier1_carriers.textpb in it.")
  private String outputDir = "/tmp/carrierconfig/out";

  @Parameter(names = "--version", description = "The version number for all output textpb.")
  private long version = 1L;

  @Parameter(names = "--consider_parent_canonical_id", arity = 1, description = "To consider parent_canonical_id")
  private static boolean considerParentCanonicalId = false;

  private static final String MCCMNC_FOR_DEFAULT_SETTINGS = "000000";

  // Resource file path to the AOSP carrier list file
  private static final String RESOURCE_CARRIER_LIST =
      "/assets/latest_carrier_id/carrier_list.textpb";

  // Constants used in parsing XMLs.
  private static final String XML_SUFFIX = ".xml";
  private static final String CARRIER_CONFIG_MCCMNC_XML_PREFIX = "carrier_config_mccmnc_";
  private static final String CARRIER_CONFIG_CID_XML_PREFIX = "carrier_config_carrierid_";
  private static final String KEY_MCCMNC_PREFIX = "mccmnc_";
  private static final String KEY_CID_PREFIX = "cid_";
  private static final String TAG_CARRIER_CONFIG = "carrier_config";

  /** Entry point when invoked from command line. */
  public static void main(String[] args) throws IOException {
    CarrierConfigConverterV2 converter = new CarrierConfigConverterV2();
    new JCommander(converter, args);
    converter.convert();
  }

  /** Entry point when invoked from other Java code, eg. the server side conversion tool. */
  public static void convert(
      String vendorXmlFile, String assetsDirName, String outputDir, long version, boolean considerParentCanonicalId)
      throws IOException {
    CarrierConfigConverterV2 converter = new CarrierConfigConverterV2();
    converter.vendorXmlFiles = ImmutableList.of(vendorXmlFile);
    converter.assetsDirName = assetsDirName;
    converter.outputDir = outputDir;
    converter.version = version;
    converter.considerParentCanonicalId = considerParentCanonicalId;
    converter.convert();
  }

  private void convert() throws IOException {
    String carriersTextpbFile = getPathAsString(outputDir, "tier1_carriers.textpb");
    String settingsTextpbDir = getPathAsString(outputDir, "setting");
    CarrierList tier1Carriers;
    ArrayList<CarrierMap> otherCarriers = new ArrayList<>();
    ArrayList<String> outFiles = new ArrayList<>();
    HashMap<CarrierId, Map<String, CarrierConfig.Config>> rawConfigs = new HashMap<>();
    TreeMap<String, CarrierConfig> tier1Configs = new TreeMap<>();
    TreeMap<String, CarrierConfig> othersConfigs = new TreeMap<>();
    DocumentBuilder xmlDocBuilder = getDocumentBuilder();
    Multimap<Integer, CarrierId> aospCarrierList = loadAospCarrierList();
    Multimap<CarrierId, Integer> reverseAospCarrierList = reverseAospCarrierList(aospCarrierList);
    Multimap<CarrierId, Integer> reverseAospCarrierListPerParentCanonicalId = reverseAospCarrierListPerParentCanonicalId();

    /*
     * High-level flow:
     * 1. Parse all input XMLs into memory
     * 2. Collect a list of interested carriers from input, represented by CarrierId.
     * 2. For each CarrierId, build its carreir configs, following AOSP DefaultCarrierConfigService.
     * 3. Merge CarrierId's as per tier1_carriers.textpb
     */

    // 1. Parse all input XMLs into memory
    Map<String, Document> assetsXmls = new HashMap<>();
    List<Document> vendorXmls = new ArrayList<>();
    // Parse assets/carrier_config_*.xml
    for (File childFile : new File(assetsDirName).listFiles()) {
      String childFileName = childFile.getName();
      String fullChildName = childFile.getCanonicalPath();
      if (childFileName.startsWith(CARRIER_CONFIG_MCCMNC_XML_PREFIX)) {
        String mccMnc =
            childFileName.substring(
                CARRIER_CONFIG_MCCMNC_XML_PREFIX.length(), childFileName.indexOf(XML_SUFFIX));
        if (!mccMnc.matches("\\d{5,6}")) {
          throw new IOException("Invalid mcc/mnc " + mccMnc + " found in " + childFileName);
        }
        try {
          assetsXmls.put(KEY_MCCMNC_PREFIX + mccMnc, parseXmlDoc(fullChildName, xmlDocBuilder));
        } catch (SAXException | IOException e) {
          throw new IOException("Failed to parse " + childFileName, e);
        }
      } else if (childFileName.startsWith(CARRIER_CONFIG_CID_XML_PREFIX)) {
        String cidAndCarrierName =
            childFileName.substring(
                CARRIER_CONFIG_CID_XML_PREFIX.length(), childFileName.indexOf(XML_SUFFIX));
        int cid = -1;
        try {
          cid = Integer.parseInt(cidAndCarrierName.split("_", -1)[0]);
        } catch (NumberFormatException e) {
          throw new IOException("Invalid carrierid found in " + childFileName, e);
        }
        try {
          assetsXmls.put(KEY_CID_PREFIX + cid, parseXmlDoc(fullChildName, xmlDocBuilder));
        } catch (SAXException | IOException e) {
          throw new IOException("Failed to parse " + childFileName, e);
        }
      }
      // ignore other malformatted files.
    }
    // Parse vendor.xml files
    for (String vendorXmlFile : vendorXmlFiles) {
      try {
        vendorXmls.add(parseXmlDoc(vendorXmlFile, xmlDocBuilder));
      } catch (SAXException | IOException e) {
        throw new IOException("Failed to parse " + vendorXmlFile, e);
      }
    }

    // 2. Collect all carriers from input, represented by CarrierId.
    List<CarrierId> carriers = new ArrayList<>();
    // Traverse <carrier_config /> labels in each file.
    for (Map.Entry<String, Document> xml : assetsXmls.entrySet()) {
      if (xml.getKey().startsWith(KEY_MCCMNC_PREFIX)) {
        String mccMnc = xml.getKey().substring(KEY_MCCMNC_PREFIX.length());
        for (Element element : getElementsByTagName(xml.getValue(), TAG_CARRIER_CONFIG)) {
          try {
            CarrierId id = parseCarrierId(element).setMccMnc(mccMnc).build();
            carriers.add(id);
          } catch (UnsupportedOperationException e) {
            throw new IOException("Unsupported syntax in assets/ for " + mccMnc, e);
          }
        }
      } else if (xml.getKey().startsWith(KEY_CID_PREFIX)) {
        int cid = Integer.parseInt(xml.getKey().substring(KEY_CID_PREFIX.length()));
        if (aospCarrierList.containsKey(cid)) {
          carriers.addAll(aospCarrierList.get(cid));
        } else {
          System.err.printf("Undefined cid %d in assets/. Ignore.\n", cid);
        }
      }
    }
    for (Document vendorXml : vendorXmls) {
      for (Element element : getElementsByTagName(vendorXml, TAG_CARRIER_CONFIG)) {
        // First, try to parse cid
        if (element.hasAttribute("cid")) {
          String cidAsString = element.getAttribute("cid");
          int cid = Integer.parseInt(cidAsString);
          if (aospCarrierList.containsKey(cid)) {
            carriers.addAll(aospCarrierList.get(cid));
          } else {
            System.err.printf("Undefined cid %d in vendor.xml. Ignore.\n", cid);
          }
        } else {
          // Then, try to parse CarrierId
          CarrierId.Builder id = parseCarrierId(element);
          // A valid mccmnc is 5- or 6-digit. But vendor.xml see special cases below:
          // Case 1: a <carrier_config> element may have neither "mcc" nor "mnc".
          // Such a tag provides configs that should be applied to all carriers, including to
          // unspecified carriers via the 000/000 default configs. Make sure 000/000 exists as
          // a carrier.
          // Case 2: a <carrier_config> element may have just "mcc" and not "mnc" for
          // country-wise config. Such a element doesn't make a carrier; but still keep it so
          // can be used if a mccmnc appears in APNs later.
          if (id.getMccMnc().isEmpty()) {
            // special case 1
            carriers.add(id.setMccMnc(MCCMNC_FOR_DEFAULT_SETTINGS).build());
          } else if (id.getMccMnc().length() == 3) {
            // special case 2
            carriers.add(id.build());
          } else if (id.getMccMnc().length() == 5 || id.getMccMnc().length() == 6) {
            // Normal mcc+mnc
            carriers.add(id.build());
          } else {
            System.err.printf("Invalid mcc/mnc: %s. Ignore.\n", id.getMccMnc());
          }
        }
      }
    }

    // 3. For each CarrierId, build its carrier configs, following AOSP DefaultCarrierConfigService.
    for (CarrierId carrier : carriers) {
      Map<String, CarrierConfig.Config> config = ImmutableMap.of();

      CarrierIdentifier id = getCid(carrier, reverseAospCarrierList, reverseAospCarrierListPerParentCanonicalId);
      if (id.getCarrierId() != -1) {
        HashMap<String, CarrierConfig.Config> configBySpecificCarrierId =
            parseCarrierConfigFromXml(
                assetsXmls.get(KEY_CID_PREFIX + id.getSpecificCarrierId()), id);
        HashMap<String, CarrierConfig.Config> configByCarrierId =
            parseCarrierConfigFromXml(assetsXmls.get(KEY_CID_PREFIX + id.getCarrierId()), id);
        HashMap<String, CarrierConfig.Config> configByMccMncFallBackCarrierId =
            parseCarrierConfigFromXml(assetsXmls.get(KEY_CID_PREFIX + id.getMccmncCarrierId()), id);
        // priority: specific carrier id > carrier id > mccmnc fallback carrier id
        if (!configBySpecificCarrierId.isEmpty()) {
          config = configBySpecificCarrierId;
        } else if (!configByCarrierId.isEmpty()) {
          config = configByCarrierId;
        } else if (!configByMccMncFallBackCarrierId.isEmpty()) {
          config = configByMccMncFallBackCarrierId;
        }
      }
      if (config.isEmpty()) {
        // fallback to use mccmnc.xml when there is no carrier id named configuration found.
        config =
            parseCarrierConfigFromXml(assetsXmls.get(KEY_MCCMNC_PREFIX + carrier.getMccMnc()), id);
      }
      // Treat vendor.xml files as if they were appended to the carrier configs read from assets.
      for (Document vendorXml : vendorXmls) {
        HashMap<String, CarrierConfig.Config> vendorConfig =
            parseCarrierConfigFromVendorXml(vendorXml, id);
        config.putAll(vendorConfig);
      }

      rawConfigs.put(carrier, config);
    }

    // Read tier1_carriers.textpb
    try (InputStream carriersTextpb = new FileInputStream(new File(carriersTextpbFile));
        BufferedReader br = new BufferedReader(new InputStreamReader(carriersTextpb, UTF_8))) {
      CarrierList.Builder builder = CarrierList.newBuilder();
      TextFormat.getParser().merge(br, builder);
      tier1Carriers = builder.build();
    }

    // Compose tier1Configs and othersConfigs from rawConfigs
    rawConfigs.forEach(
        (carrierId, configs) -> {
          String cname = getCanonicalName(tier1Carriers, carrierId);
          CarrierConfig.Builder ccb = toCarrierConfigBuilder(configs);
          if (cname != null) { // tier-1 carrier
            if (tier1Configs.containsKey(cname)) {
              tier1Configs.put(
                  cname, CarrierProtoUtils.mergeCarrierConfig(tier1Configs.get(cname), ccb));
            } else {
              tier1Configs.put(cname, ccb.build());
            }
          } else { // other carrier
            cname = generateCanonicalNameForOthers(carrierId);
            otherCarriers.add(
                CarrierMap.newBuilder().addCarrierId(carrierId).setCanonicalName(cname).build());
            othersConfigs.put(cname, ccb.build());
          }
        });

    // output tier1 carrier settings
    for (int i = 0; i < tier1Carriers.getEntryCount(); i++) {
      CarrierMap cm = tier1Carriers.getEntry(i);
      String cname = cm.getCanonicalName();
      String fileName = getPathAsString(settingsTextpbDir, cname + ".textpb");

      outFiles.add(fileName);

      try (OutputStream os = new FileOutputStream(new File(fileName));
          BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os, UTF_8))) {
        CarrierSettings.Builder cs = CarrierSettings.newBuilder().setCanonicalName(cname);
        if (tier1Configs.containsKey(cname)) {
          cs.setConfigs(sortConfig(tier1Configs.get(cname)).toBuilder().build());
        }
        cs.setVersion(version);
        TextFormat.printUnicode(cs.build(), bw);
      }
    }

    // Output other carriers list
    String otherCarriersFile = getPathAsString(outputDir, "other_carriers.textpb");
    outFiles.add(otherCarriersFile);
    CarrierProtoUtils.sortCarrierMapEntries(otherCarriers);
    try (OutputStream os = new FileOutputStream(new File(otherCarriersFile));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os, UTF_8))) {
      CarrierList cl =
          CarrierList.newBuilder().addAllEntry(otherCarriers).setVersion(version).build();
      TextFormat.printUnicode(cl, bw);
    }

    // Output other carriers settings
    String othersFileName = getPathAsString(settingsTextpbDir, "others.textpb");
    outFiles.add(othersFileName);
    try (OutputStream os = new FileOutputStream(new File(othersFileName));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os, UTF_8))) {
      MultiCarrierSettings.Builder mcs = MultiCarrierSettings.newBuilder().setVersion(version);
      othersConfigs.forEach(
          (cname, cc) -> {
            mcs.addSetting(
                CarrierSettings.newBuilder()
                    .setCanonicalName(cname)
                    .setConfigs(sortConfig(cc).toBuilder().build())
                    .build());
          });
      TextFormat.printUnicode(mcs.build(), bw);
    }

    // Print out the list of all output file names
    System.out.println("SUCCESS! Files generated:");
    for (String fileName : outFiles) {
      System.out.println(fileName);
    }
  }

  private static DocumentBuilder getDocumentBuilder() {
    try {
      DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
      return dbFactory.newDocumentBuilder();
    } catch (ParserConfigurationException e) {
      throw new IllegalStateException(e);
    }
  }

  private static Multimap<Integer, CarrierId> loadAospCarrierList() throws IOException {
    com.android.providers.telephony.CarrierIdProto.CarrierList.Builder aospCarrierList =
        com.android.providers.telephony.CarrierIdProto.CarrierList.newBuilder();
    try (InputStream textpb =
            CarrierConfigConverterV2.class.getResourceAsStream(RESOURCE_CARRIER_LIST);
        BufferedReader textpbReader = new BufferedReader(new InputStreamReader(textpb, UTF_8))) {
      TextFormat.getParser().merge(textpbReader, aospCarrierList);
    }
    return aospCarrierList.getCarrierIdList().stream()
        .collect(
            flatteningToMultimap(
                cid -> cid.getCanonicalId(),
                cid -> carrierAttributeToCarrierId(cid.getCarrierAttributeList()).stream(),
                MultimapBuilder.linkedHashKeys().arrayListValues()::build));
  }

  private static Multimap<CarrierId, Integer> reverseAospCarrierListPerParentCanonicalId() throws IOException {

    com.android.providers.telephony.CarrierIdProto.CarrierList.Builder aospCarrierList =
            com.android.providers.telephony.CarrierIdProto.CarrierList.newBuilder();
    try (InputStream textpb =
                 CarrierConfigConverterV2.class.getResourceAsStream(RESOURCE_CARRIER_LIST);
         BufferedReader textpbReader = new BufferedReader(new InputStreamReader(textpb, UTF_8))) {
      TextFormat.getParser().merge(textpbReader, aospCarrierList);
    }
    Multimap<Integer, CarrierId> res = aospCarrierList.getCarrierIdList().stream()
            .filter(cid -> cid.getParentCanonicalId() > 0)
            .collect(
                    flatteningToMultimap(
                            cid -> cid.getParentCanonicalId(),
                            cid -> carrierAttributeToCarrierId(cid.getCarrierAttributeList()).stream(),
                            MultimapBuilder.linkedHashKeys().arrayListValues()::build));

    return res.entries().stream()
        .collect(
            toMultimap(
                entry -> entry.getValue(),
                entry -> entry.getKey(),
                MultimapBuilder.linkedHashKeys().arrayListValues()::build));
  }

  // Convert `CarrierAttribute`s to `CarrierId`s.
  // A CarrierAttribute message with fields not supported by CarrierSettings, like preferred_apn,
  // is ignored.
  private static ImmutableList<CarrierId> carrierAttributeToCarrierId(
      List<CarrierAttribute> carrierAttributes) {
    List<CarrierId> result = new ArrayList<>();
    ImmutableSet<Descriptors.FieldDescriptor> supportedFields =
        ImmutableSet.of(
            CarrierAttribute.getDescriptor().findFieldByName("mccmnc_tuple"),
            CarrierAttribute.getDescriptor().findFieldByName("imsi_prefix_xpattern"),
            CarrierAttribute.getDescriptor().findFieldByName("spn"),
            CarrierAttribute.getDescriptor().findFieldByName("gid1"));
    for (CarrierAttribute carrierAttribute : carrierAttributes) {
      if (!carrierAttribute.getAllFields().keySet().stream().allMatch(supportedFields::contains)) {
        // This `CarrierAttribute` contains unsupported fields; skip.
        continue;
      }
      for (String mccmnc : carrierAttribute.getMccmncTupleList()) {
        CarrierId.Builder carrierId = CarrierId.newBuilder().setMccMnc(mccmnc);
        if (carrierAttribute.getImsiPrefixXpatternCount() > 0) {
          for (String imsi : carrierAttribute.getImsiPrefixXpatternList()) {
            result.add(carrierId.setImsi(imsi).build());
          }
        } else if (carrierAttribute.getGid1Count() > 0) {
          for (String gid1 : carrierAttribute.getGid1List()) {
            result.add(carrierId.setGid1(gid1).build());
          }
        } else if (carrierAttribute.getSpnCount() > 0) {
          for (String spn : carrierAttribute.getSpnList()) {
            // Some SPN has trailng space character \r, messing up textpb. Remove them.
            // It won't affect CarrierSettings which uses prefix matching for SPN.
            result.add(carrierId.setSpn(CharMatcher.whitespace().trimTrailingFrom(spn)).build());
          }
        } else { // Ignore other attributes not supported by CarrierSettings
          result.add(carrierId.build());
        }
      }
    }
    // Dedup
    return ImmutableSet.copyOf(result).asList();
  }

  private static Multimap<CarrierId, Integer> reverseAospCarrierList(
      Multimap<Integer, CarrierId> aospCarrierList) {
    return aospCarrierList.entries().stream()
        .collect(
            toMultimap(
                entry -> entry.getValue(),
                entry -> entry.getKey(),
                MultimapBuilder.linkedHashKeys().arrayListValues()::build));
  }

  private static Document parseXmlDoc(String fileName, DocumentBuilder xmlDocBuilder)
      throws SAXException, IOException {
    try (InputStream configXml = new FileInputStream(new File(fileName))) {
      Document xmlDoc = xmlDocBuilder.parse(configXml);
      xmlDoc.getDocumentElement().normalize();
      return xmlDoc;
    }
  }

  private static ImmutableList<Element> getElementsByTagName(Document xmlDoc, String tagName) {
    if (xmlDoc == null) {
      return ImmutableList.of();
    }
    ImmutableList.Builder<Element> result = new ImmutableList.Builder<>();
    xmlDoc.getDocumentElement().normalize();
    NodeList nodeList = xmlDoc.getElementsByTagName(tagName);
    for (int i = 0; i < nodeList.getLength(); i++) {
      Node node = nodeList.item(i);
      if (node.getNodeType() == Node.ELEMENT_NODE) {
        result.add((Element) node);
      }
    }
    return result.build();
  }

  static CarrierConfig sortConfig(CarrierConfig in) {
    final CarrierConfig.Builder result = in.toBuilder().clearConfig();
    in.getConfigList().stream()
        .sorted(comparing(CarrierConfig.Config::getKey))
        .forEachOrdered((c) -> result.addConfig(c));
    return result.build();
  }

  static String getCanonicalName(CarrierList pList, CarrierId pId) {
    for (int i = 0; i < pList.getEntryCount(); i++) {
      CarrierMap cm = pList.getEntry(i);
      for (int j = 0; j < cm.getCarrierIdCount(); j++) {
        CarrierId cid = cm.getCarrierId(j);
        if (cid.equals(pId)) {
          return cm.getCanonicalName();
        }
      }
    }
    return null;
  }

  static String generateCanonicalNameForOthers(CarrierId pId) {
    // Not a tier-1 carrier: generate name
    StringBuilder genName = new StringBuilder(pId.getMccMnc());
    switch (pId.getMvnoDataCase()) {
      case GID1:
        genName.append("GID1=");
        genName.append(Ascii.toUpperCase(pId.getGid1()));
        break;
      case SPN:
        genName.append("SPN=");
        genName.append(Ascii.toUpperCase(pId.getSpn()));
        break;
      case IMSI:
        genName.append("IMSI=");
        genName.append(Ascii.toUpperCase(pId.getImsi()));
        break;
      default: // MVNODATA_NOT_SET
        // Do nothing
    }
    return genName.toString();
  }

  /**
   * Converts a map with carrier configs to a {@link CarrierConfig.Builder}.
   *
   * @see #parseCarrierConfigToMap
   */
  private static CarrierConfig.Builder toCarrierConfigBuilder(
      Map<String, CarrierConfig.Config> configs) {
    CarrierConfig.Builder builder = CarrierConfig.newBuilder();
    configs.forEach(
        (key, value) -> {
          builder.addConfig(value.toBuilder().setKey(key));
        });
    return builder;
  }

  /**
   * Returns a map with carrier configs parsed from a assets/*.xml.
   *
   * @return a map, key being the carrier config key, value being a {@link CarrierConfig.Config}
   *     with one of the value set.
   */
  private static HashMap<String, CarrierConfig.Config> parseCarrierConfigFromXml(
      Document xmlDoc, CarrierIdentifier carrier) throws IOException {
    HashMap<String, CarrierConfig.Config> configMap = new HashMap<>();
    for (Element element : getElementsByTagName(xmlDoc, TAG_CARRIER_CONFIG)) {
      if (carrier != null && !checkFilters(element, carrier)) {
        continue;
      }
      configMap.putAll(parseCarrierConfigToMap(element));
    }
    return configMap;
  }

  /**
   * Returns a map with carrier configs parsed from the vendor.xml.
   *
   * @return a map, key being the carrier config key, value being a {@link CarrierConfig.Config}
   *     with one of the value set.
   */
  private static HashMap<String, CarrierConfig.Config> parseCarrierConfigFromVendorXml(
      Document xmlDoc, CarrierIdentifier carrier) throws IOException {
    HashMap<String, CarrierConfig.Config> configMap = new HashMap<>();
    for (Element element : getElementsByTagName(xmlDoc, TAG_CARRIER_CONFIG)) {
      if (carrier != null && !checkFilters(element, carrier)) {
        continue;
      }
      configMap.putAll(parseCarrierConfigToMap(element));
    }
    return configMap;
  }

  /**
   * Returns a map with carrier configs parsed from the XML element.
   *
   * @return a map, key being the carrier config key, value being a {@link CarrierConfig.Config}
   *     with one of the value set.
   */
  private static HashMap<String, CarrierConfig.Config> parseCarrierConfigToMap(Element element)
      throws IOException {
    HashMap<String, CarrierConfig.Config> configMap = new HashMap<>();
    NodeList nList;
    // bool value
    nList = element.getElementsByTagName("boolean");
    for (int i = 0; i < nList.getLength(); i++) {
      Node nNode = nList.item(i);
      if (nNode.getNodeType() != Node.ELEMENT_NODE ||
          !nNode.getParentNode().isSameNode(element)) {
        continue;
      }
      Element eElement = (Element) nNode;
      String key = eElement.getAttribute("name");
      boolean value = Boolean.parseBoolean(eElement.getAttribute("value"));
      configMap.put(key, CarrierConfig.Config.newBuilder().setBoolValue(value).build());
    }
    // int value
    nList = element.getElementsByTagName("int");
    for (int i = 0; i < nList.getLength(); i++) {
      Node nNode = nList.item(i);
      if (nNode.getNodeType() != Node.ELEMENT_NODE ||
          !nNode.getParentNode().isSameNode(element)) {
        continue;
      }
      Element eElement = (Element) nNode;
      String key = eElement.getAttribute("name");
      int value = Integer.parseInt(eElement.getAttribute("value"));
      configMap.put(key, CarrierConfig.Config.newBuilder().setIntValue(value).build());
    }
    // long value
    nList = element.getElementsByTagName("long");
    for (int i = 0; i < nList.getLength(); i++) {
      Node nNode = nList.item(i);
      if (nNode.getNodeType() != Node.ELEMENT_NODE ||
          !nNode.getParentNode().isSameNode(element)) {
        continue;
      }
      Element eElement = (Element) nNode;
      String key = eElement.getAttribute("name");
      long value = Long.parseLong(eElement.getAttribute("value"));
      configMap.put(key, CarrierConfig.Config.newBuilder().setLongValue(value).build());
    }
    // double value
    nList = element.getElementsByTagName("double");
    for (int i = 0; i < nList.getLength(); i++) {
      Node nNode = nList.item(i);
      if (nNode.getNodeType() != Node.ELEMENT_NODE ||
          !nNode.getParentNode().isSameNode(element)) {
        continue;
      }
      Element eElement = (Element) nNode;
      String key = eElement.getAttribute("name");
      double value = Double.parseDouble(eElement.getAttribute("value"));
      configMap.put(key, CarrierConfig.Config.newBuilder().setDoubleValue(value).build());
    }
    // text value
    nList = element.getElementsByTagName("string");
    for (int i = 0; i < nList.getLength(); i++) {
      Node nNode = nList.item(i);
      if (nNode.getNodeType() != Node.ELEMENT_NODE ||
          !nNode.getParentNode().isSameNode(element)) {
        continue;
      }
      Element eElement = (Element) nNode;
      String key = eElement.getAttribute("name");
      String value = String.valueOf(eElement.getTextContent());
      if (value.isEmpty()) {
        value = eElement.getAttribute("value");
      }
      configMap.put(key, CarrierConfig.Config.newBuilder().setTextValue(value).build());
    }
    // text array
    nList = element.getElementsByTagName("string-array");
    for (int i = 0; i < nList.getLength(); i++) {
      Node nNode = nList.item(i);
      if (nNode.getNodeType() != Node.ELEMENT_NODE ||
          !nNode.getParentNode().isSameNode(element)) {
        continue;
      }
      Element eElement = (Element) nNode;
      String key = eElement.getAttribute("name");
      CarrierConfig.Config.Builder cccb = CarrierConfig.Config.newBuilder();
      TextArray.Builder cctb = TextArray.newBuilder();
      NodeList subList = eElement.getElementsByTagName("item");
      for (int j = 0; j < subList.getLength(); j++) {
        Node subNode = subList.item(j);
        if (subNode.getNodeType() != Node.ELEMENT_NODE) {
          continue;
        }
        Element subElement = (Element) subNode;
        String value = String.valueOf(subElement.getAttribute("value"));
        cctb.addItem(value);
      }
      configMap.put(key, cccb.setTextArray(cctb.build()).build());
    }
    // int array
    nList = element.getElementsByTagName("int-array");
    for (int i = 0; i < nList.getLength(); i++) {
      Node nNode = nList.item(i);
      if (nNode.getNodeType() != Node.ELEMENT_NODE ||
          !nNode.getParentNode().isSameNode(element)) {
        continue;
      }
      Element eElement = (Element) nNode;
      String key = eElement.getAttribute("name");
      CarrierConfig.Config.Builder cccb = CarrierConfig.Config.newBuilder();
      IntArray.Builder ccib = IntArray.newBuilder();
      NodeList subList = eElement.getElementsByTagName("item");
      for (int j = 0; j < subList.getLength(); j++) {
        Node subNode = subList.item(j);
        if (subNode.getNodeType() != Node.ELEMENT_NODE) {
          continue;
        }
        Element subElement = (Element) subNode;
        int value = Integer.parseInt(subElement.getAttribute("value"));
        ccib.addItem(value);
      }
      configMap.put(key, cccb.setIntArray(ccib.build()).build());
    }
    // pbundle_as_map
    nList = element.getElementsByTagName("pbundle_as_map");
    for (int i = 0; i < nList.getLength(); i++) {
      Node nNode = nList.item(i);
      if (nNode.getNodeType() != Node.ELEMENT_NODE ||
          !nNode.getParentNode().isSameNode(element)) {
        continue;
      }
      Element eElement = (Element) nNode;
      String key = eElement.getAttribute("name");
      HashMap<String, CarrierConfig.Config> value = parseCarrierConfigToMap(eElement);
      configMap.put(key, CarrierConfig.Config.newBuilder()
          .setBundle(toCarrierConfigBuilder(value)).build());
    }
    return configMap;
  }

  /**
   * Returns {@code true} if a <carrier_config ...> element matches the carrier identifier.
   *
   * <p>Copied from AOSP DefaultCarrierConfigService.
   */
  private static boolean checkFilters(Element element, CarrierIdentifier id) {
    boolean result = true;
    NamedNodeMap attributes = element.getAttributes();
    for (int i = 0; i < attributes.getLength(); i++) {
      String attribute = attributes.item(i).getNodeName();
      String value = attributes.item(i).getNodeValue();
      switch (attribute) {
        case "mcc":
          result = result && value.equals(id.getMcc());
          break;
        case "mnc":
          result = result && value.equals(id.getMnc());
          break;
        case "gid1":
          result = result && Ascii.equalsIgnoreCase(value, id.getGid1());
          break;
        case "spn":
          result = result && matchOnSP(value, id);
          break;
        case "imsi":
          result = result && matchOnImsi(value, id);
          break;
        case "cid":
          result =
              result
                  && ((Integer.parseInt(value) == id.getCarrierId())
                      || (Integer.parseInt(value) == id.getSpecificCarrierId()));
          break;
        case "name":
          // name is used together with cid for readability. ignore for filter.
          break;
        default:
          System.err.println("Unsupported attribute " + attribute + "=" + value);
          result = false;
      }
    }
    return result;
  }

  /**
   * Returns {@code true} if an "spn" attribute in <carrier_config ...> element matches the carrier
   * identifier.
   *
   * <p>Copied from AOSP DefaultCarrierConfigService.
   */
  private static boolean matchOnSP(String xmlSP, CarrierIdentifier id) {
    boolean matchFound = false;

    String currentSP = id.getSpn();
    // <carrier_config ... spn="null"> means expecting SIM SPN empty in AOSP convention.
    if (Ascii.equalsIgnoreCase("null", xmlSP)) {
      if (currentSP.isEmpty()) {
        matchFound = true;
      }
    } else if (currentSP != null) {
      Pattern spPattern = Pattern.compile(xmlSP, Pattern.CASE_INSENSITIVE);
      Matcher matcher = spPattern.matcher(currentSP);
      matchFound = matcher.matches();
    }
    return matchFound;
  }

  /**
   * Returns {@code true} if an "imsi" attribute in <carrier_config ...> element matches the carrier
   * identifier.
   *
   * <p>Copied from AOSP DefaultCarrierConfigService.
   */
  private static boolean matchOnImsi(String xmlImsi, CarrierIdentifier id) {
    boolean matchFound = false;

    String currentImsi = id.getImsi();
    // If we were able to retrieve current IMSI, see if it matches.
    if (currentImsi != null) {
      Pattern imsiPattern = Pattern.compile(xmlImsi, Pattern.CASE_INSENSITIVE);
      Matcher matcher = imsiPattern.matcher(currentImsi);
      matchFound = matcher.matches();
    }
    return matchFound;
  }

  /**
   * Parses a {@link CarrierId} out of a <carrier_config ...> tag.
   *
   * <p>This is purely used for discover potential carriers expressed by this tag, the return value
   * may not reflect all attributes of the tag.
   */
  private static CarrierId.Builder parseCarrierId(Element element) {
    CarrierId.Builder builder = CarrierId.newBuilder();
    String mccMnc = element.getAttribute("mcc") + element.getAttribute("mnc");
    builder.setMccMnc(mccMnc);
    if (element.hasAttribute("imsi")) {
      builder.setImsi(element.getAttribute("imsi"));
    } else if (element.hasAttribute("gid1")) {
      builder.setGid1(element.getAttribute("gid1"));
    } else if (element.hasAttribute("gid2")) {
      throw new UnsupportedOperationException(
          "Not support attribute `gid2`: " + element.getAttribute("gid2"));
    } else if (element.hasAttribute("spn")) {
      builder.setSpn(element.getAttribute("spn"));
    }
    return builder;
  }

  // Same as {@link java.nio.file.Paths#get} but returns a String
  private static String getPathAsString(String first, String... more) {
    return java.nio.file.Paths.get(first, more).toString();
  }

  /** Mirror of Android CarrierIdentifier class. Default value of a carrier id is -1. */
  @AutoValue
  abstract static class CarrierIdentifier {
    abstract String getMcc();

    abstract String getMnc();

    abstract String getImsi();

    abstract String getGid1();

    abstract String getSpn();

    abstract int getCarrierId();

    abstract int getSpecificCarrierId();

    abstract int getMccmncCarrierId();

    static CarrierIdentifier create(
        CarrierId carrier, int carrierId, int specificCarrierId, int mccmncCarrierId) {
      String mcc = carrier.getMccMnc().substring(0, 3);
      String mnc = carrier.getMccMnc().length() > 3 ? carrier.getMccMnc().substring(3) : "";
      return new AutoValue_CarrierConfigConverterV2_CarrierIdentifier(
          mcc,
          mnc,
          carrier.getImsi(),
          carrier.getGid1(),
          carrier.getSpn(),
          carrierId,
          specificCarrierId,
          mccmncCarrierId);
    }
  }

  private static CarrierIdentifier getCid(
      CarrierId carrierId, Multimap<CarrierId, Integer> reverseAospCarrierList,
        Multimap<CarrierId, Integer> reverseAospCarrierListPerParentCanonicalId) {
    // Mimic TelephonyManager#getCarrierIdFromMccMnc, which is implemented by
    // CarrierResolver#getCarrierIdFromMccMnc.
    CarrierId mccMnc = CarrierId.newBuilder().setMccMnc(carrierId.getMccMnc()).build();
    int mccMncCarrierId = reverseAospCarrierList.get(mccMnc).stream().findFirst().orElse(-1);
    List<Integer> cids = ImmutableList.copyOf(reverseAospCarrierList.get(carrierId));
    int parentCanonicalId = getParentCanonicalId(carrierId, cids, reverseAospCarrierListPerParentCanonicalId);
    // No match: use -1
    if (cids.isEmpty()) {
      if (considerParentCanonicalId) {
        return CarrierIdentifier.create(carrierId, parentCanonicalId, -1, mccMncCarrierId);
      } else {
	return CarrierIdentifier.create(carrierId, -1, -1, mccMncCarrierId);
      }
    }
    // One match: use as both carrierId and specificCarrierId
    if (cids.size() == 1) {
      if (considerParentCanonicalId) {
        return CarrierIdentifier.create(carrierId, parentCanonicalId, cids.get(0), mccMncCarrierId);
      } else {
        return CarrierIdentifier.create(carrierId, cids.get(0), cids.get(0), mccMncCarrierId);
      }
    }
    // Two matches:  specificCarrierId is always bigger than carrierId
    if (cids.size() == 2) {
      if (considerParentCanonicalId) {
        return CarrierIdentifier.create(
            carrierId,
            parentCanonicalId,
            Math.max(cids.get(0), cids.get(1)),
            mccMncCarrierId);
      } else {
        return CarrierIdentifier.create(
            carrierId,
            Math.min(cids.get(0), cids.get(1)),
            Math.max(cids.get(0), cids.get(1)),
            mccMncCarrierId);
      }
    }
    // Cannot be more than 2 matches.
    throw new IllegalStateException("More than two cid's found for " + carrierId + ": " + cids);
  }

  private static int getParentCanonicalId(
      CarrierId carrierId,
      List<Integer> cids,
      Multimap<CarrierId, Integer> reverseAospCarrierListPerParentCanonicalId) {

    List<Integer> parentCids = ImmutableList.copyOf(reverseAospCarrierListPerParentCanonicalId.get(carrierId));
    if (cids.isEmpty()) {
      if (parentCids.isEmpty()) {
        return -1;
      } else {
        return parentCids.get(0);
      }
    } else if (cids.size() == 1) {
      if (parentCids.isEmpty()) {
        return cids.get(0);
      } else {
        return parentCids.get(0);
      }
    } else if (cids.size() == 2) {
      if (parentCids.isEmpty()) {
        return Math.min(cids.get(0), cids.get(1));
      } else {
        return parentCids.get(0);
      }
    } else {
      return -1;
    }
  }
  private CarrierConfigConverterV2() {}
}
