/*
 * Copyright (C) 2012 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.PhoneNumberUtil.PhoneNumberType;
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
import com.google.i18n.phonenumbers.prefixmapper.PrefixTimeZonesMap;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * An offline mapper from phone numbers to time zones.
 */
public class PhoneNumberToTimeZonesMapper {
  private static PhoneNumberToTimeZonesMapper instance = null;
  private static final String MAPPING_DATA_DIRECTORY =
      "/com/google/i18n/phonenumbers/timezones/data/";
  private static final String MAPPING_DATA_FILE_NAME = "map_data";
  // This is defined by ICU as the unknown time zone.
  private static final String UNKNOWN_TIMEZONE = "Etc/Unknown";
  // A list with the ICU unknown time zone as single element.
  // @VisibleForTesting
  static final List<String> UNKNOWN_TIME_ZONE_LIST = new ArrayList<String>(1);
  static {
    UNKNOWN_TIME_ZONE_LIST.add(UNKNOWN_TIMEZONE);
  }

  private static final Logger LOGGER =
      Logger.getLogger(PhoneNumberToTimeZonesMapper.class.getName());

  private PrefixTimeZonesMap prefixTimeZonesMap = null;

  // @VisibleForTesting
  PhoneNumberToTimeZonesMapper(String prefixTimeZonesMapDataDirectory) {
    this.prefixTimeZonesMap = loadPrefixTimeZonesMapFromFile(
        prefixTimeZonesMapDataDirectory + MAPPING_DATA_FILE_NAME);
  }

  private PhoneNumberToTimeZonesMapper(PrefixTimeZonesMap prefixTimeZonesMap) {
    this.prefixTimeZonesMap = prefixTimeZonesMap;
  }

  private static PrefixTimeZonesMap loadPrefixTimeZonesMapFromFile(String path) {
    InputStream source = PhoneNumberToTimeZonesMapper.class.getResourceAsStream(path);
    ObjectInputStream in = null;
    PrefixTimeZonesMap map = new PrefixTimeZonesMap();
    try {
      in = new ObjectInputStream(source);
      map.readExternal(in);
    } catch (IOException e) {
      LOGGER.log(Level.WARNING, e.toString());
    } finally {
      close(in);
    }
    return map;
  }

  private static void close(InputStream in) {
    if (in != null) {
      try {
        in.close();
      } catch (IOException e) {
        LOGGER.log(Level.WARNING, e.toString());
      }
    }
  }

  /**
   * Helper class used for lazy instantiation of a PhoneNumberToTimeZonesMapper. This also loads the
   * map data in a thread-safe way.
   */
  private static class LazyHolder {
    private static final PhoneNumberToTimeZonesMapper INSTANCE;
    static {
      PrefixTimeZonesMap map =
          loadPrefixTimeZonesMapFromFile(MAPPING_DATA_DIRECTORY + MAPPING_DATA_FILE_NAME);
      INSTANCE = new PhoneNumberToTimeZonesMapper(map);
    }
  }

  /**
   * Gets a {@link PhoneNumberToTimeZonesMapper} instance.
   *
   * <p> The {@link PhoneNumberToTimeZonesMapper} is implemented as a singleton. Therefore, calling
   * this method multiple times will only result in one instance being created.
   *
   * @return  a {@link PhoneNumberToTimeZonesMapper} instance
   */
  public static synchronized PhoneNumberToTimeZonesMapper getInstance() {
    return LazyHolder.INSTANCE;
  }

  /**
   * Returns a list of time zones to which a phone number belongs.
   *
   * <p>This method assumes the validity of the number passed in has already been checked, and that
   * the number is geo-localizable. We consider fixed-line and mobile numbers possible candidates
   * for geo-localization.
   *
   * @param number  a valid phone number for which we want to get the time zones to which it belongs
   * @return  a list of the corresponding time zones or a single element list with the default
   *     unknown time zone if no other time zone was found or if the number was invalid
   */
  public List<String> getTimeZonesForGeographicalNumber(PhoneNumber number) {
    return getTimeZonesForGeocodableNumber(number);
  }

  /**
   * As per {@link #getTimeZonesForGeographicalNumber(PhoneNumber)} but explicitly checks
   * the validity of the number passed in.
   *
   * @param number  the phone number for which we want to get the time zones to which it belongs
   * @return  a list of the corresponding time zones or a single element list with the default
   *     unknown time zone if no other time zone was found or if the number was invalid
   */
  public List<String> getTimeZonesForNumber(PhoneNumber number) {
    PhoneNumberType numberType = PhoneNumberUtil.getInstance().getNumberType(number);
    if (numberType == PhoneNumberType.UNKNOWN) {
      return UNKNOWN_TIME_ZONE_LIST;
    } else if (!canBeGeocoded(numberType)) {
      return getCountryLevelTimeZonesforNumber(number);
    }
    return getTimeZonesForGeographicalNumber(number);
  }

  /**
   * A similar method is implemented as PhoneNumberUtil.isNumberGeographical, which performs a
   * stricter check, as it determines if a number has a geographical association. Also, if new
   * phone number types were added, we should check if this other method should be updated too.
   * TODO: Remove duplication by completing the logic in the method in PhoneNumberUtil.
   *                   For more information, see the comments in that method.
   */
  private boolean canBeGeocoded(PhoneNumberType numberType) {
    return (numberType == PhoneNumberType.FIXED_LINE ||
            numberType == PhoneNumberType.MOBILE ||
            numberType == PhoneNumberType.FIXED_LINE_OR_MOBILE);
  }

  /**
   * Returns a String with the ICU unknown time zone.
   */
  public static String getUnknownTimeZone() {
    return UNKNOWN_TIMEZONE;
  }

  /**
   * Returns a list of time zones to which a geocodable phone number belongs.
   *
   * @param number  the phone number for which we want to get the time zones to which it belongs
   * @return  the list of corresponding  time zones or a single element list with the default
   *     unknown time zone if no other time zone was found or if the number was invalid
   */
  private List<String> getTimeZonesForGeocodableNumber(PhoneNumber number) {
    List<String> timezones = prefixTimeZonesMap.lookupTimeZonesForNumber(number);
    return Collections.unmodifiableList(timezones.isEmpty() ? UNKNOWN_TIME_ZONE_LIST
                                                            : timezones);
  }

  /**
   * Returns the list of time zones corresponding to the country calling code of {@code number}.
   *
   * @param number  the phone number to look up
   * @return  the list of corresponding time zones or a single element list with the default
   *     unknown time zone if no other time zone was found
   */
  private List<String> getCountryLevelTimeZonesforNumber(PhoneNumber number) {
    List<String> timezones = prefixTimeZonesMap.lookupCountryLevelTimeZonesForNumber(number);
    return Collections.unmodifiableList(timezones.isEmpty() ? UNKNOWN_TIME_ZONE_LIST
                                                            : timezones);
  }
}
