package edu.brynmawr.ple2;

import android.content.Context;
import android.util.Log;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;

public class DataCities
{

	private static DataCities instance=null;
	private ArrayList<City> cities;
	private Hashtable<String,String> stateAbbrevs;

	private static final int MAX_CITIES = 500;

	private DataCities()
	{
		cities = new ArrayList<>();
	}

	public static DataCities getInstance(Context act)
	{
		if (instance==null)
		{
			instance=new DataCities();
			instance.loadAbbrevs(act);
			instance.loadCities(act);
			instance.loadLongLat(act);
		}
		return instance;
	}

	public static DataCities getInstance()
	{
		return instance;
	}

	private void loadAbbrevs(Context act) {
		stateAbbrevs = new Hashtable<>();
		try (BufferedReader bis =
					 new BufferedReader(new InputStreamReader(act.getResources().openRawResource(R.raw.abbrev))))
		{
			String line;
			while ((line=bis.readLine()) != null)
			{
				try
				{
					String[] ll = line.toLowerCase().split(",");
					stateAbbrevs.put(ll[0], ll[1]);
					stateAbbrevs.put(ll[1], ll[0]);
				}
				catch (ArrayIndexOutOfBoundsException aoe)
				{
					Log.e("THISS", "Problem with " + line + " " + aoe);
				}
			}
		}
		catch (Exception e)
		{
			Log.e("THISS", "Problem reading cities", e);
		}

	}
	private void loadCities(Context act)
	{
		try (BufferedReader bis =
					 new BufferedReader(new InputStreamReader(act.getResources().openRawResource(R.raw.cities))))
		{
			String line;
			int linecount = 0;
			while ((line=bis.readLine()) != null)
			{
				try
				{
					cities.add(new City(line));
				}
				catch (ArrayIndexOutOfBoundsException aoe)
				{
					Log.e("THISS", "Problem with " + line + " " + aoe);
				}
				linecount++;
				if (linecount>MAX_CITIES)
					break;
			}
		}
		catch (Exception e)
		{
			Log.e("THISS", "Problem reading cities", e);
		}
		Collections.sort(cities);
	}

	private void loadLongLat(Context act) {
		Hashtable<String, City> ch = new Hashtable<>();
		for (City c : cities) {
			Log.i("THISS", c.name+c.state);
			ch.put((c.name+stateAbbrevs.get(c.state.toLowerCase())).toLowerCase(), c);
		}
		try (BufferedReader bis =
					 new BufferedReader(new InputStreamReader(act.getResources().openRawResource(R.raw.ziplocs))))
		{
			String line;
			bis.readLine();
			while ((line=bis.readLine()) != null)
			{

				String[] ll = line.replace("\"", "").split(",");
				if (ll.length > 7) {
					try {
						if (ll[6].length()>0) {
							float longi = Float.parseFloat(ll[6]);
							float lati = Float.parseFloat(ll[5]);
							String cs = (ll[2]+ll[3]).toLowerCase();
							City c = ch.get(cs);
							if (c != null) {
								c.addLongLat(longi, lati);
							} else {
								//Log.i("THISS", "unknown "+cs);
							}
						}
					} catch (Exception ee) {
						Log.e("THISS", "problem " + line, ee);
					}
				}
			}
		}
		catch (Exception e)
		{
			Log.e("THISS", "Problem reading cities", e);
		}
		ArrayList<City> nc = new ArrayList<>();
		for (City c : cities) {
			boolean cc = c.normalizeLongitudeLatitude();
			if (cc)
				nc.add(c);
			//Log.i("THISS", c.name + " " + c.getLongitude() + " " + c.getLatitude());
		}
		cities=nc;
		Collections.sort(cities);
	}

	public ArrayList<City> getCitiesInState(String state)
	{
		//Log.i("THISS", "STATE FOR CITIES " + state);
		ArrayList<City> rtn = new ArrayList<City>();
		for (City c : cities)
		{
			if (c.state.equals(state))
				rtn.add(c);
		}
		return rtn;
	}

	public City getCityFromNumber(int number)
	{
		for (City c : cities)
		{
			if (c.position == number)
				return c;
		}
		return cities.get(114);
	}
	public City getCityFromNumber(String numString)
	{
		try
		{
			return getCityFromNumber(Integer.parseInt(numString));
		}
		catch (Exception ee)
		{
			return getCityFromNumber(114);
		}
	}

	public void sortByDistance() {
		City.sortBy = City.SortBy.distance;
		Collections.sort(cities);
	}

	public ArrayList<City> getCities()
	{
		return cities;
	}

	public String[] getCityNameArray()
	{
		String[] rtn = new String[cities.size()];
		for (int i=0; i<cities.size(); i++)
			rtn[i] = cities.get(i).name + " " + cities.get(i).state;
		return rtn;
	}

	public City getCity(int cLoc)
	{
		return cities.get(cLoc);
	}

	public static String state2Region(String stte)
	{
		String[][] regs = {{
				"New England",
				"Maine",
				"New Hampshire",
				"Vermont",
				"Massachusetts",
				"Rhode Island",
				"Connecticut",
		},

				{"Middle Atlantic",
						"New York",
						"Pennsylvania",
						"New Jersey",
				},

				{"East North Central",
						"Wisconsin",
						"Michigan",
						"Illinois",
						"Indiana",
						"Ohio",
				},

				{"West North Central",
						"North Dakota",
						"South Dakota",
						"Nebraska",
						"Kansas",
						"Minnesota",
						"Iowa",
						"Missouri",
				},

				{"South Atlantic",
						"Delaware",
						"Maryland",
						"District of Columbia",
						"Virginia",
						"West Virginia",
						"North Carolina",
						"South Carolina",
						"Georgia",
						"Florida",
				},

				{"East South Central",
						"Kentucky",
						"Tennessee",
						"Mississippi",
						"Alabama",
				},

				{"West South Central",
						"Oklahoma",
						"Texas",
						"Arkansas",
						"Louisiana",
				},

				{"Mountain",
						"Idaho",
						"Montana",
						"Wyoming",
						"Nevada",
						"Utah",
						"Colorado",
						"Arizona",
						"New Mexico",
				},

				{"Pacific",
						"Alaska",
						"Washington",
						"Oregon",
						"California",
						"Hawaii",
				}};

		for (String[]rl : regs)
			for (int i=1; i<rl.length; i++)
			{
				if (rl[i].equals(stte))
					return rl[0];
			}
		return "";
	}

}
