/*
 * Copyright (C) 2011 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.android.i18n.phonenumbers.geocoding;

import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber;
import junit.framework.TestCase;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * Unittests for AreaCodeMap.java
 *
 * @author Shaopeng Jia
 */
public class AreaCodeMapTest extends TestCase {
  private final AreaCodeMap areaCodeMapForUS = new AreaCodeMap();
  private final AreaCodeMap areaCodeMapForIT = new AreaCodeMap();
  private PhoneNumber number = new PhoneNumber();

  public AreaCodeMapTest() {
    SortedMap<Integer, String> sortedMapForUS = new TreeMap<Integer, String>();
    sortedMapForUS.put(1212, "New York");
    sortedMapForUS.put(1480, "Arizona");
    sortedMapForUS.put(1650, "California");
    sortedMapForUS.put(1907, "Alaska");
    sortedMapForUS.put(1201664, "Westwood, NJ");
    sortedMapForUS.put(1480893, "Phoenix, AZ");
    sortedMapForUS.put(1501372, "Little Rock, AR");
    sortedMapForUS.put(1626308, "Alhambra, CA");
    sortedMapForUS.put(1650345, "San Mateo, CA");
    sortedMapForUS.put(1867993, "Dawson, YT");
    sortedMapForUS.put(1972480, "Richardson, TX");

    areaCodeMapForUS.readAreaCodeMap(sortedMapForUS);

    SortedMap<Integer, String> sortedMapForIT = new TreeMap<Integer, String>();
    sortedMapForIT.put(3902, "Milan");
    sortedMapForIT.put(3906, "Rome");
    sortedMapForIT.put(39010, "Genoa");
    sortedMapForIT.put(390131, "Alessandria");
    sortedMapForIT.put(390321, "Novara");
    sortedMapForIT.put(390975, "Potenza");

    areaCodeMapForIT.readAreaCodeMap(sortedMapForIT);
  }

  private static SortedMap<Integer, String> createDefaultStorageMapCandidate() {
    SortedMap<Integer, String> sortedMap = new TreeMap<Integer, String>();
    // Make the area codes bigger to store them using integer.
    sortedMap.put(121212345, "New York");
    sortedMap.put(148034434, "Arizona");
    return sortedMap;
  }

  private static SortedMap<Integer, String> createFlyweightStorageMapCandidate() {
    SortedMap<Integer, String> sortedMap = new TreeMap<Integer, String>();
    sortedMap.put(1212, "New York");
    sortedMap.put(1213, "New York");
    sortedMap.put(1214, "New York");
    sortedMap.put(1480, "Arizona");
    return sortedMap;
  }

  public void testGetSmallerMapStorageChoosesDefaultImpl() {
    AreaCodeMapStorageStrategy mapStorage =
        new AreaCodeMap().getSmallerMapStorage(createDefaultStorageMapCandidate());
    assertFalse(mapStorage instanceof FlyweightMapStorage);
  }

  public void testGetSmallerMapStorageChoosesFlyweightImpl() {
    AreaCodeMapStorageStrategy mapStorage =
        new AreaCodeMap().getSmallerMapStorage(createFlyweightStorageMapCandidate());
    assertTrue(mapStorage instanceof FlyweightMapStorage);
  }

  public void testLookupInvalidNumber_US() {
    // central office code cannot start with 1.
    number.setCountryCode(1).setNationalNumber(2121234567L);
    assertEquals("New York", areaCodeMapForUS.lookup(number));
  }

  public void testLookupNumber_NJ() {
    number.setCountryCode(1).setNationalNumber(2016641234L);
    assertEquals("Westwood, NJ", areaCodeMapForUS.lookup(number));
  }

  public void testLookupNumber_NY() {
    number.setCountryCode(1).setNationalNumber(2126641234L);
    assertEquals("New York", areaCodeMapForUS.lookup(number));
  }

  public void testLookupNumber_CA_1() {
    number.setCountryCode(1).setNationalNumber(6503451234L);
    assertEquals("San Mateo, CA", areaCodeMapForUS.lookup(number));
  }

  public void testLookupNumber_CA_2() {
    number.setCountryCode(1).setNationalNumber(6502531234L);
    assertEquals("California", areaCodeMapForUS.lookup(number));
  }

  public void testLookupNumberFound_TX() {
    number.setCountryCode(1).setNationalNumber(9724801234L);
    assertEquals("Richardson, TX", areaCodeMapForUS.lookup(number));
  }

  public void testLookupNumberNotFound_TX() {
    number.setCountryCode(1).setNationalNumber(9724811234L);
    assertNull(areaCodeMapForUS.lookup(number));
  }

  public void testLookupNumber_CH() {
    number.setCountryCode(41).setNationalNumber(446681300L);
    assertNull(areaCodeMapForUS.lookup(number));
  }

  public void testLookupNumber_IT() {
    number.setCountryCode(39).setNationalNumber(212345678L).setItalianLeadingZero(true);
    assertEquals("Milan", areaCodeMapForIT.lookup(number));

    number.setNationalNumber(612345678L);
    assertEquals("Rome", areaCodeMapForIT.lookup(number));

    number.setNationalNumber(3211234L);
    assertEquals("Novara", areaCodeMapForIT.lookup(number));

    // A mobile number
    number.setNationalNumber(321123456L).setItalianLeadingZero(false);
    assertNull(areaCodeMapForIT.lookup(number));

    // An invalid number (too short)
    number.setNationalNumber(321123L).setItalianLeadingZero(true);
    assertEquals("Novara", areaCodeMapForIT.lookup(number));
  }

  /**
   * Creates a new area code map serializing the provided area code map to a stream and then reading
   * this stream. The resulting area code map is expected to be strictly equal to the provided one
   * from which it was generated.
   */
  private static AreaCodeMap createNewAreaCodeMap(AreaCodeMap areaCodeMap) throws IOException {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
    areaCodeMap.writeExternal(objectOutputStream);
    objectOutputStream.flush();

    AreaCodeMap newAreaCodeMap = new AreaCodeMap();
    newAreaCodeMap.readExternal(
        new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray())));
    return newAreaCodeMap;
  }

  public void testReadWriteExternalWithDefaultStrategy() throws IOException {
    AreaCodeMap localAreaCodeMap = new AreaCodeMap();
    localAreaCodeMap.readAreaCodeMap(createDefaultStorageMapCandidate());
    assertFalse(localAreaCodeMap.getAreaCodeMapStorage() instanceof FlyweightMapStorage);

    AreaCodeMap newAreaCodeMap;
    newAreaCodeMap = createNewAreaCodeMap(localAreaCodeMap);
    assertEquals(localAreaCodeMap.toString(), newAreaCodeMap.toString());
  }

  public void testReadWriteExternalWithFlyweightStrategy() throws IOException {
    AreaCodeMap localAreaCodeMap = new AreaCodeMap();
    localAreaCodeMap.readAreaCodeMap(createFlyweightStorageMapCandidate());
    assertTrue(localAreaCodeMap.getAreaCodeMapStorage() instanceof FlyweightMapStorage);

    AreaCodeMap newAreaCodeMap;
    newAreaCodeMap = createNewAreaCodeMap(localAreaCodeMap);
    assertEquals(localAreaCodeMap.toString(), newAreaCodeMap.toString());
  }
}
