package ca.tremblett.ddj;

import java.util.Collections;
import java.util.Hashtable;
import java.util.SortedSet;
import java.util.TreeSet;

public class CanadaInfo {

  String[] provinces;
  String[] provincesAndTerritories;
  String[] territories;

  Hashtable capitalsByName = new Hashtable();
  Hashtable capitalsByPostalAbbreviation = new Hashtable();
  Hashtable areaByName = new Hashtable();
  Hashtable areaByPostalAbbreviation = new Hashtable();
  Hashtable populationByName = new Hashtable();
  Hashtable populationByPostalAbbreviation = new Hashtable();
  Hashtable premierByName = new Hashtable();
  Hashtable premierByPostalAbbreviation = new Hashtable();

  static String[][] data = {
    {"Newfoundland and Labrador","NL","P","St. John's",
     "405212","512930","Danny Williams"},
    {"Nova Scotia","NS","P","Halifax",
     "55284","908007","John Hamm"},
    {"New Brunswick","NB","P","Fredericton",
     "72908","729498","Bernard Lord"},
    {"Prince Edward Island","PE","P","Charlottetown",
     "5660","135294","Pat Binns"},
    {"Quebec","QC","P","Quebec City",    
     "1542056","7237479","Jean Charset"},
    {"Ontario","ON","P","Toronto",
     "1076395","11410046","Dalton McGuinty"},
    {"Manitoba","MB","P","Winnipeg",
     "647797","1119583","Gary Doer"},
    {"Saskatchewan","SK","P","Regina",
     "651036","978933","Lorne Calvert"},
    {"Alberta","AB","P","Edmonton",
     "661848","2974807","Ralph Klein"},
    {"British Columbia","BC","P","Victoria",
     "944735","3907738","Gordon Campbell"},
    {"Yukon","YT","T","Whitehorse",
     "482443","28674","Dennis Fentie"},
    {"Northwest Territories","NT","T","Yellowknife",
     "1346106","37360","Joe Handley"},
    {"Nunavut","NU","T","Iqaluit",
     "2093190","24730","Paul Okalik"}
    };

  private static final String ERROR_MESSAGE =
    " is not a valid province or territory";

  public CanadaInfo() throws Exception {
    init();
  }

  private void init() throws Exception {
    SortedSet provinceSet = 
      Collections.synchronizedSortedSet(new TreeSet());
    SortedSet territorySet = 
      Collections.synchronizedSortedSet(new TreeSet());
    SortedSet provincesAndTerritoriesSet = 
      Collections.synchronizedSortedSet(new TreeSet());
    for (int i = 0; i < data.length; ++i) {
      String name = data[i][0];
      String postalAbbreviation = data[i][1];
      if (data[i][2].equals("P")) {
        provinceSet.add(name);
      }
      else {
        territorySet.add(name);
      }
      provincesAndTerritoriesSet.add(name);
      String capital = data[i][3];
      capitalsByName.put(name,capital);
      capitalsByPostalAbbreviation.put(postalAbbreviation,capital);
      int area = Integer.parseInt(data[i][4]);
      areaByName.put(name,new Integer(area));
      areaByPostalAbbreviation.put(postalAbbreviation,
          new Integer(area));
      int population = Integer.parseInt(data[i][5]);
      populationByName.put(name,new Integer(population));
      populationByPostalAbbreviation.put(postalAbbreviation,
          new Integer(population));
      String premier = data[i][6];
      premierByName.put(name,premier);
      premierByPostalAbbreviation.put(postalAbbreviation,premier);
    }
    provinces = new String[provinceSet.size()];
    territories = new String[territorySet.size()];
    provincesAndTerritories = 
      new String[provincesAndTerritoriesSet.size()];
    provinces = (String[])provinceSet.toArray(provinces);
    territories = (String[])territorySet.toArray(territories);
    provincesAndTerritories = 
      (String[])provincesAndTerritoriesSet.toArray(
        provincesAndTerritories);
    for (int i = 0; i < provinces.length; ++i) {
      System.out.println(provinces[i]);
    }
  }

  public String[] provinces() {
    return provinces;
  }

  public String[] provincesAndTerritories() {
    return provincesAndTerritories;
  }

  public String[] territories() {
    return territories;
  }

  public String capital(String provinceOrTerritory) 
      throws Exception {
    if (capitalsByName.containsKey(provinceOrTerritory)) {
      return (String)capitalsByName.get(provinceOrTerritory);
    }
    else if (capitalsByPostalAbbreviation.containsKey(
               provinceOrTerritory)) {
      return (String)capitalsByPostalAbbreviation.get(
        provinceOrTerritory);
    }
    else {
      throw new Exception("is not a valid province or territory");
    }
  }

  public int area(String provinceOrTerritory) throws Exception {
    if (areaByName.containsKey(provinceOrTerritory)) {
      return ((Integer)areaByName.get(
        provinceOrTerritory)).intValue();
    }
    else if (areaByPostalAbbreviation.containsKey(
               provinceOrTerritory)) {
      return ((Integer)areaByPostalAbbreviation.get(
        provinceOrTerritory)).intValue();
    }
    else {
      throw new Exception(provinceOrTerritory + ERROR_MESSAGE);
    }
  }

  public int population(String provinceOrTerritory) throws Exception {
    if (populationByName.containsKey(provinceOrTerritory)) {
      return ((Integer)populationByName.get(
        provinceOrTerritory)).intValue();
    }
    else if (populationByPostalAbbreviation.containsKey(
               provinceOrTerritory)) {
      return ((Integer)populationByPostalAbbreviation.get(
        provinceOrTerritory)).intValue();
    }
    else {
      throw new Exception(provinceOrTerritory + ERROR_MESSAGE);
    }
  }

  public String premier(String provinceOrTerritory) throws Exception {
    if (premierByName.containsKey(provinceOrTerritory)) {
      return (String)premierByName.get(provinceOrTerritory);
    }
    else if (premierByPostalAbbreviation.containsKey(
      provinceOrTerritory)) {
      return (String)premierByPostalAbbreviation.get(
        provinceOrTerritory);
    }
    else {
      throw new Exception(provinceOrTerritory + ERROR_MESSAGE);
    }
  }
}
