/*
 * Copyright (C) 2013 The Libphonenumber Authors
 *
 * 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.i18n.phonenumbers;

import com.google.i18n.phonenumbers.internal.MatcherApi;
import com.google.i18n.phonenumbers.internal.RegexBasedMatcher;
import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata;
import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc;
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;

/**
 * Methods for getting information about short phone numbers, such as short codes and emergency
 * numbers. Note that most commercial short numbers are not handled here, but by the
 * {@link PhoneNumberUtil}.
 *
 * @author Shaopeng Jia
 * @author David Yonge-Mallo
 */
public class ShortNumberInfo {
  private static final Logger logger = Logger.getLogger(ShortNumberInfo.class.getName());

  private static final ShortNumberInfo INSTANCE =
      new ShortNumberInfo(RegexBasedMatcher.create());

  // In these countries, if extra digits are added to an emergency number, it no longer connects
  // to the emergency service.
  private static final Set<String> REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT =
      new HashSet<String>();
  static {
    REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.add("BR");
    REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.add("CL");
    REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.add("NI");
  }

  /** Cost categories of short numbers. */
  public enum ShortNumberCost {
    TOLL_FREE,
    STANDARD_RATE,
    PREMIUM_RATE,
    UNKNOWN_COST
  }

  /** Returns the singleton instance of the ShortNumberInfo. */
  public static ShortNumberInfo getInstance() {
    return INSTANCE;
  }

  // MatcherApi supports the basic matching method for checking if a given national number matches
  // a national number patten or a possible number patten defined in the given
  // {@code PhoneNumberDesc}.
  private final MatcherApi matcherApi;

  // A mapping from a country calling code to the region codes which denote the region represented
  // by that country calling code. In the case of multiple regions sharing a calling code, such as
  // the NANPA regions, the one indicated with "isMainCountryForCode" in the metadata should be
  // first.
  private final Map<Integer, List<String>> countryCallingCodeToRegionCodeMap;

  // @VisibleForTesting
  ShortNumberInfo(MatcherApi matcherApi) {
    this.matcherApi = matcherApi;
    // TODO: Create ShortNumberInfo for a given map
    this.countryCallingCodeToRegionCodeMap =
        CountryCodeToRegionCodeMap.getCountryCodeToRegionCodeMap();
  }

  /**
   * Returns a list with the region codes that match the specific country calling code. For
   * non-geographical country calling codes, the region code 001 is returned. Also, in the case
   * of no region code being found, an empty list is returned.
   */
  private List<String> getRegionCodesForCountryCode(int countryCallingCode) {
    List<String> regionCodes = countryCallingCodeToRegionCodeMap.get(countryCallingCode);
    return Collections.unmodifiableList(regionCodes == null ? new ArrayList<String>(0)
                                                            : regionCodes);
  }

  /**
   * Helper method to check that the country calling code of the number matches the region it's
   * being dialed from.
   */
  private boolean regionDialingFromMatchesNumber(PhoneNumber number,
      String regionDialingFrom) {
    List<String> regionCodes = getRegionCodesForCountryCode(number.getCountryCode());
    return regionCodes.contains(regionDialingFrom);
  }

  /**
   * Check whether a short number is a possible number when dialled from a region, given the number
   * in the form of a string, and the region where the number is dialed from. This provides a more
   * lenient check than {@link #isValidShortNumberForRegion}.
   *
   * @param shortNumber the short number to check as a string
   * @param regionDialingFrom the region from which the number is dialed
   * @return whether the number is a possible short number
   * @deprecated Anyone who was using it and passing in a string with whitespace (or other
   *             formatting characters) would have been getting the wrong result. You should parse
   *             the string to PhoneNumber and use the method
   *             {@code #isPossibleShortNumberForRegion(PhoneNumber, String)}. This method will be
   *             removed in the next release.
   */
  @Deprecated
  public boolean isPossibleShortNumberForRegion(String shortNumber, String regionDialingFrom) {
    PhoneMetadata phoneMetadata =
        MetadataManager.getShortNumberMetadataForRegion(regionDialingFrom);
    if (phoneMetadata == null) {
      return false;
    }
    return matcherApi.matchesPossibleNumber(shortNumber, phoneMetadata.getGeneralDesc());
  }

  /**
   * Check whether a short number is a possible number when dialed from the given region. This
   * provides a more lenient check than {@link #isValidShortNumberForRegion}.
   *
   * @param number the short number to check
   * @param regionDialingFrom the region from which the number is dialed
   * @return whether the number is a possible short number
   */
  public boolean isPossibleShortNumberForRegion(PhoneNumber number, String regionDialingFrom) {
    if (!regionDialingFromMatchesNumber(number, regionDialingFrom)) {
      return false;
    }
    PhoneMetadata phoneMetadata =
        MetadataManager.getShortNumberMetadataForRegion(regionDialingFrom);
    if (phoneMetadata == null) {
      return false;
    }
    return matcherApi.matchesPossibleNumber(getNationalSignificantNumber(number),
        phoneMetadata.getGeneralDesc());
  }

  /**
   * Check whether a short number is a possible number. If a country calling code is shared by
   * multiple regions, this returns true if it's possible in any of them. This provides a more
   * lenient check than {@link #isValidShortNumber}. See {@link
   * #isPossibleShortNumberForRegion(PhoneNumber, String)} for details.
   *
   * @param number the short number to check
   * @return whether the number is a possible short number
   */
  public boolean isPossibleShortNumber(PhoneNumber number) {
    List<String> regionCodes = getRegionCodesForCountryCode(number.getCountryCode());
    String shortNumber = getNationalSignificantNumber(number);
    for (String region : regionCodes) {
      PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(region);
      if (phoneMetadata == null) {
        continue;
      }
      if (matcherApi.matchesPossibleNumber(shortNumber, phoneMetadata.getGeneralDesc())) {
        return true;
      }
    }
    return false;
  }

  /**
   * Tests whether a short number matches a valid pattern in a region. Note that this doesn't verify
   * the number is actually in use, which is impossible to tell by just looking at the number
   * itself.
   *
   * @param shortNumber the short number to check as a string
   * @param regionDialingFrom the region from which the number is dialed
   * @return whether the short number matches a valid pattern
   * @deprecated Anyone who was using it and passing in a string with whitespace (or other
   *             formatting characters) would have been getting the wrong result. You should parse
   *             the string to PhoneNumber and use the method
   *             {@code #isValidShortNumberForRegion(PhoneNumber, String)}. This method will be
   *             removed in the next release.
   */
  @Deprecated
  public boolean isValidShortNumberForRegion(String shortNumber, String regionDialingFrom) {
    PhoneMetadata phoneMetadata =
        MetadataManager.getShortNumberMetadataForRegion(regionDialingFrom);
    if (phoneMetadata == null) {
      return false;
    }
    PhoneNumberDesc generalDesc = phoneMetadata.getGeneralDesc();
    if (!matchesPossibleNumberAndNationalNumber(shortNumber, generalDesc)) {
      return false;
    }
    PhoneNumberDesc shortNumberDesc = phoneMetadata.getShortCode();
    return matchesPossibleNumberAndNationalNumber(shortNumber, shortNumberDesc);
  }

  /**
   * Tests whether a short number matches a valid pattern in a region. Note that this doesn't verify
   * the number is actually in use, which is impossible to tell by just looking at the number
   * itself.
   *
   * @param number the short number for which we want to test the validity
   * @param regionDialingFrom the region from which the number is dialed
   * @return whether the short number matches a valid pattern
   */
  public boolean isValidShortNumberForRegion(PhoneNumber number, String regionDialingFrom) {
    if (!regionDialingFromMatchesNumber(number, regionDialingFrom)) {
      return false;
    }
    PhoneMetadata phoneMetadata =
        MetadataManager.getShortNumberMetadataForRegion(regionDialingFrom);
    if (phoneMetadata == null) {
      return false;
    }
    String shortNumber = getNationalSignificantNumber(number);
    PhoneNumberDesc generalDesc = phoneMetadata.getGeneralDesc();
    if (!matchesPossibleNumberAndNationalNumber(shortNumber, generalDesc)) {
      return false;
    }
    PhoneNumberDesc shortNumberDesc = phoneMetadata.getShortCode();
    return matchesPossibleNumberAndNationalNumber(shortNumber, shortNumberDesc);
  }

  /**
   * Tests whether a short number matches a valid pattern. If a country calling code is shared by
   * multiple regions, this returns true if it's valid in any of them. Note that this doesn't verify
   * the number is actually in use, which is impossible to tell by just looking at the number
   * itself. See {@link #isValidShortNumberForRegion(PhoneNumber, String)} for details.
   *
   * @param number the short number for which we want to test the validity
   * @return whether the short number matches a valid pattern
   */
  public boolean isValidShortNumber(PhoneNumber number) {
    List<String> regionCodes = getRegionCodesForCountryCode(number.getCountryCode());
    String regionCode = getRegionCodeForShortNumberFromRegionList(number, regionCodes);
    if (regionCodes.size() > 1 && regionCode != null) {
      // If a matching region had been found for the phone number from among two or more regions,
      // then we have already implicitly verified its validity for that region.
      return true;
    }
    return isValidShortNumberForRegion(number, regionCode);
  }

  /**
   * Gets the expected cost category of a short number when dialled from a region (however, nothing
   * is implied about its validity). If it is important that the number is valid, then its validity
   * must first be checked using {@link isValidShortNumberForRegion}. Note that emergency numbers
   * are always considered toll-free. Example usage:
   * <pre>{@code
   * ShortNumberInfo shortInfo = ShortNumberInfo.getInstance();
   * String shortNumber = "110";
   * String regionCode = "FR";
   * if (shortInfo.isValidShortNumberForRegion(shortNumber, regionCode)) {
   *   ShortNumberInfo.ShortNumberCost cost = shortInfo.getExpectedCostForRegion(shortNumber,
   *       regionCode);
   *   // Do something with the cost information here.
   * }}</pre>
   *
   * @param shortNumber the short number for which we want to know the expected cost category,
   *     as a string
   * @param regionDialingFrom the region from which the number is dialed
   * @return the expected cost category for that region of the short number. Returns UNKNOWN_COST if
   *     the number does not match a cost category. Note that an invalid number may match any cost
   *     category.
   * @deprecated Anyone who was using it and passing in a string with whitespace (or other
   *             formatting characters) would have been getting the wrong result. You should parse
   *             the string to PhoneNumber and use the method
   *             {@code #getExpectedCostForRegion(PhoneNumber, String)}. This method will be
   *             removed in the next release.
   */
  @Deprecated
  public ShortNumberCost getExpectedCostForRegion(String shortNumber, String regionDialingFrom) {
    // Note that regionDialingFrom may be null, in which case phoneMetadata will also be null.
    PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(
        regionDialingFrom);
    if (phoneMetadata == null) {
      return ShortNumberCost.UNKNOWN_COST;
    }

    // The cost categories are tested in order of decreasing expense, since if for some reason the
    // patterns overlap the most expensive matching cost category should be returned.
    if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getPremiumRate())) {
      return ShortNumberCost.PREMIUM_RATE;
    }
    if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getStandardRate())) {
      return ShortNumberCost.STANDARD_RATE;
    }
    if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getTollFree())) {
      return ShortNumberCost.TOLL_FREE;
    }
    if (isEmergencyNumber(shortNumber, regionDialingFrom)) {
      // Emergency numbers are implicitly toll-free.
      return ShortNumberCost.TOLL_FREE;
    }
    return ShortNumberCost.UNKNOWN_COST;
  }

  /**
   * Gets the expected cost category of a short number when dialed from a region (however, nothing
   * is implied about its validity). If it is important that the number is valid, then its validity
   * must first be checked using {@link #isValidShortNumberForRegion}. Note that emergency numbers
   * are always considered toll-free. Example usage:
   * <pre>{@code
   * // The region for which the number was parsed and the region we subsequently check against
   * // need not be the same. Here we parse the number in the US and check it for Canada.
   * PhoneNumber number = phoneUtil.parse("110", "US");
   * ...
   * String regionCode = "CA";
   * ShortNumberInfo shortInfo = ShortNumberInfo.getInstance();
   * if (shortInfo.isValidShortNumberForRegion(shortNumber, regionCode)) {
   *   ShortNumberCost cost = shortInfo.getExpectedCostForRegion(number, regionCode);
   *   // Do something with the cost information here.
   * }}</pre>
   *
   * @param number the short number for which we want to know the expected cost category
   * @param regionDialingFrom the region from which the number is dialed
   * @return the expected cost category for that region of the short number. Returns UNKNOWN_COST if
   *     the number does not match a cost category. Note that an invalid number may match any cost
   *     category.
   */
  public ShortNumberCost getExpectedCostForRegion(PhoneNumber number, String regionDialingFrom) {
    if (!regionDialingFromMatchesNumber(number, regionDialingFrom)) {
      return ShortNumberCost.UNKNOWN_COST;
    }
    // Note that regionDialingFrom may be null, in which case phoneMetadata will also be null.
    PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(
        regionDialingFrom);
    if (phoneMetadata == null) {
      return ShortNumberCost.UNKNOWN_COST;
    }

    String shortNumber = getNationalSignificantNumber(number);

    // The cost categories are tested in order of decreasing expense, since if for some reason the
    // patterns overlap the most expensive matching cost category should be returned.
    if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getPremiumRate())) {
      return ShortNumberCost.PREMIUM_RATE;
    }
    if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getStandardRate())) {
      return ShortNumberCost.STANDARD_RATE;
    }
    if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getTollFree())) {
      return ShortNumberCost.TOLL_FREE;
    }
    if (isEmergencyNumber(shortNumber, regionDialingFrom)) {
      // Emergency numbers are implicitly toll-free.
      return ShortNumberCost.TOLL_FREE;
    }
    return ShortNumberCost.UNKNOWN_COST;
  }

  /**
   * Gets the expected cost category of a short number (however, nothing is implied about its
   * validity). If the country calling code is unique to a region, this method behaves exactly the
   * same as {@link #getExpectedCostForRegion(PhoneNumber, String)}. However, if the country
   * calling code is shared by multiple regions, then it returns the highest cost in the sequence
   * PREMIUM_RATE, UNKNOWN_COST, STANDARD_RATE, TOLL_FREE. The reason for the position of
   * UNKNOWN_COST in this order is that if a number is UNKNOWN_COST in one region but STANDARD_RATE
   * or TOLL_FREE in another, its expected cost cannot be estimated as one of the latter since it
   * might be a PREMIUM_RATE number.
   * <p>
   * For example, if a number is STANDARD_RATE in the US, but TOLL_FREE in Canada, the expected
   * cost returned by this method will be STANDARD_RATE, since the NANPA countries share the same
   * country calling code.
   * <p>
   * Note: If the region from which the number is dialed is known, it is highly preferable to call
   * {@link #getExpectedCostForRegion(PhoneNumber, String)} instead.
   *
   * @param number the short number for which we want to know the expected cost category
   * @return the highest expected cost category of the short number in the region(s) with the given
   *     country calling code
   */
  public ShortNumberCost getExpectedCost(PhoneNumber number) {
    List<String> regionCodes = getRegionCodesForCountryCode(number.getCountryCode());
    if (regionCodes.size() == 0) {
      return ShortNumberCost.UNKNOWN_COST;
    }
    if (regionCodes.size() == 1) {
      return getExpectedCostForRegion(number, regionCodes.get(0));
    }
    ShortNumberCost cost = ShortNumberCost.TOLL_FREE;
    for (String regionCode : regionCodes) {
      ShortNumberCost costForRegion = getExpectedCostForRegion(number, regionCode);
      switch (costForRegion) {
        case PREMIUM_RATE:
          return ShortNumberCost.PREMIUM_RATE;
        case UNKNOWN_COST:
          cost = ShortNumberCost.UNKNOWN_COST;
          break;
        case STANDARD_RATE:
          if (cost != ShortNumberCost.UNKNOWN_COST) {
            cost = ShortNumberCost.STANDARD_RATE;
          }
          break;
        case TOLL_FREE:
          // Do nothing.
          break;
        default:
          logger.log(Level.SEVERE, "Unrecognised cost for region: " + costForRegion);
      }
    }
    return cost;
  }

  // Helper method to get the region code for a given phone number, from a list of possible region
  // codes. If the list contains more than one region, the first region for which the number is
  // valid is returned.
  private String getRegionCodeForShortNumberFromRegionList(PhoneNumber number,
                                                           List<String> regionCodes) {
    if (regionCodes.size() == 0) {
      return null;
    } else if (regionCodes.size() == 1) {
      return regionCodes.get(0);
    }
    String nationalNumber = getNationalSignificantNumber(number);
    for (String regionCode : regionCodes) {
      PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode);
      if (phoneMetadata != null
          && matchesPossibleNumberAndNationalNumber(nationalNumber, phoneMetadata.getShortCode())) {
        // The number is valid for this region.
        return regionCode;
      }
    }
    return null;
  }

  /**
   * Convenience method to get a list of what regions the library has metadata for.
   */
  Set<String> getSupportedRegions() {
    return Collections.unmodifiableSet(MetadataManager.getShortNumberMetadataSupportedRegions());
  }

  /**
   * Gets a valid short number for the specified region.
   *
   * @param regionCode the region for which an example short number is needed
   * @return a valid short number for the specified region. Returns an empty string when the
   *     metadata does not contain such information.
   */
  // @VisibleForTesting
  String getExampleShortNumber(String regionCode) {
    PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode);
    if (phoneMetadata == null) {
      return "";
    }
    PhoneNumberDesc desc = phoneMetadata.getShortCode();
    if (desc.hasExampleNumber()) {
      return desc.getExampleNumber();
    }
    return "";
  }

  /**
   * Gets a valid short number for the specified cost category.
   *
   * @param regionCode the region for which an example short number is needed
   * @param cost the cost category of number that is needed
   * @return a valid short number for the specified region and cost category. Returns an empty
   *     string when the metadata does not contain such information, or the cost is UNKNOWN_COST.
   */
  // @VisibleForTesting
  String getExampleShortNumberForCost(String regionCode, ShortNumberCost cost) {
    PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode);
    if (phoneMetadata == null) {
      return "";
    }
    PhoneNumberDesc desc = null;
    switch (cost) {
      case TOLL_FREE:
        desc = phoneMetadata.getTollFree();
        break;
      case STANDARD_RATE:
        desc = phoneMetadata.getStandardRate();
        break;
      case PREMIUM_RATE:
        desc = phoneMetadata.getPremiumRate();
        break;
      default:
        // UNKNOWN_COST numbers are computed by the process of elimination from the other cost
        // categories.
    }
    if (desc != null && desc.hasExampleNumber()) {
      return desc.getExampleNumber();
    }
    return "";
  }

  /**
   * Returns true if the given number, exactly as dialed, might be used to connect to an emergency
   * service in the given region.
   * <p>
   * This method accepts a string, rather than a PhoneNumber, because it needs to distinguish
   * cases such as "+1 911" and "911", where the former may not connect to an emergency service in
   * all cases but the latter would. This method takes into account cases where the number might
   * contain formatting, or might have additional digits appended (when it is okay to do that in
   * the specified region).
   *
   * @param number the phone number to test
   * @param regionCode the region where the phone number is being dialed
   * @return whether the number might be used to connect to an emergency service in the given region
   */
  public boolean connectsToEmergencyNumber(String number, String regionCode) {
    return matchesEmergencyNumberHelper(number, regionCode, true /* allows prefix match */);
  }

  /**
   * Returns true if the given number exactly matches an emergency service number in the given
   * region.
   * <p>
   * This method takes into account cases where the number might contain formatting, but doesn't
   * allow additional digits to be appended. Note that {@code isEmergencyNumber(number, region)}
   * implies {@code connectsToEmergencyNumber(number, region)}.
   *
   * @param number the phone number to test
   * @param regionCode the region where the phone number is being dialed
   * @return whether the number exactly matches an emergency services number in the given region
   */
  public boolean isEmergencyNumber(String number, String regionCode) {
    return matchesEmergencyNumberHelper(number, regionCode, false /* doesn't allow prefix match */);
  }

  private boolean matchesEmergencyNumberHelper(String number, String regionCode,
      boolean allowPrefixMatch) {
    number = PhoneNumberUtil.extractPossibleNumber(number);
    if (PhoneNumberUtil.PLUS_CHARS_PATTERN.matcher(number).lookingAt()) {
      // Returns false if the number starts with a plus sign. We don't believe dialing the country
      // code before emergency numbers (e.g. +1911) works, but later, if that proves to work, we can
      // add additional logic here to handle it.
      return false;
    }
    PhoneMetadata metadata = MetadataManager.getShortNumberMetadataForRegion(regionCode);
    if (metadata == null || !metadata.hasEmergency()) {
      return false;
    }

    String normalizedNumber = PhoneNumberUtil.normalizeDigitsOnly(number);
    PhoneNumberDesc emergencyDesc = metadata.getEmergency();
    boolean allowPrefixMatchForRegion =
        allowPrefixMatch && !REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.contains(regionCode);
    return matcherApi.matchesNationalNumber(normalizedNumber, emergencyDesc,
        allowPrefixMatchForRegion);
  }

  /**
   * Given a valid short number, determines whether it is carrier-specific (however, nothing is
   * implied about its validity). If it is important that the number is valid, then its validity
   * must first be checked using {@link #isValidShortNumber} or
   * {@link #isValidShortNumberForRegion}.
   *
   * @param number the valid short number to check
   * @return whether the short number is carrier-specific (assuming the input was a valid short
   *     number).
   */
  public boolean isCarrierSpecific(PhoneNumber number) {
    List<String> regionCodes = getRegionCodesForCountryCode(number.getCountryCode());
    String regionCode = getRegionCodeForShortNumberFromRegionList(number, regionCodes);
    String nationalNumber = getNationalSignificantNumber(number);
    PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode);
    return (phoneMetadata != null)
        && (matchesPossibleNumberAndNationalNumber(nationalNumber,
                phoneMetadata.getCarrierSpecific()));
  }

  /**
   * Gets the national significant number of the a phone number. Note a national significant number
   * doesn't contain a national prefix or any formatting.
   * <p>
   * This is a temporary duplicate of the {@code getNationalSignificantNumber} method from
   * {@code PhoneNumberUtil}. Ultimately a canonical static version should exist in a separate
   * utility class (to prevent {@code ShortNumberInfo} needing to depend on PhoneNumberUtil).
   *
   * @param number  the phone number for which the national significant number is needed
   * @return  the national significant number of the PhoneNumber object passed in
   */
  private static String getNationalSignificantNumber(PhoneNumber number) {
    // If leading zero(s) have been set, we prefix this now. Note this is not a national prefix.
    StringBuilder nationalNumber = new StringBuilder();
    if (number.isItalianLeadingZero()) {
      char[] zeros = new char[number.getNumberOfLeadingZeros()];
      Arrays.fill(zeros, '0');
      nationalNumber.append(new String(zeros));
    }
    nationalNumber.append(number.getNationalNumber());
    return nationalNumber.toString();
  }

  // TODO: Once we have benchmarked ShortNumberInfo, consider if it is worth keeping
  // this performance optimization, and if so move this into the matcher implementation.
  private boolean matchesPossibleNumberAndNationalNumber(String number,
      PhoneNumberDesc numberDesc) {
    return matcherApi.matchesPossibleNumber(number, numberDesc)
        && matcherApi.matchesNationalNumber(number, numberDesc, false);
  }
}
