public class LocationAlertsEvents {
    public static final String LOCATION_RECEIVED = "LocationReceived";
} public class LocationLogic {
    public static int getUpdateIntervalMinutes(Context context, float overrideSetting) {
        // Get stored value
        float sliderValue = Singleton.getSharedPreferences(context).getFloat(context.getString(R.string.gpsFrequencyPref), 0.02f);

        // Override it?
        if (overrideSetting != -1) {
            sliderValue = overrideSetting;
        }

        // Calculate frequency in minutes
        int frequencyMin = (int) (LocationAlerts.MAX_FREQUENCY_MIN * sliderValue);

        // Return it
        return frequencyMin;
    }

    public static int getMaxDistanceKilometers(Context context, float overrideSetting) {
        // Get stored value
        float sliderValue = Singleton.getSharedPreferences(context).getFloat(context.getString(R.string.maxDistancePref), 0.04f);

        // Override it?
        if (overrideSetting != -1) {
            sliderValue = overrideSetting;
        }

        // Calculate frequency in minutes
        int maxDistance = (int) (LocationAlerts.MAX_DISTANCE_KM * sliderValue);

        // Return it
        return maxDistance;
    }

    public static long getUpdateIntervalMilliseconds(Context context) {
        // Convert to milliseconds
        return getUpdateIntervalMinutes(context, -1) * 60 * 1000;
    }

    public static boolean shouldRequestLocationUpdates(Context context) {
        // Must have Google Play Services
        if (!GooglePlayServices.isAvailable(context)) {
            return false;
        }

        // Get location alerts enabled setting
        boolean locationAlerts = Singleton.getSharedPreferences(context).getBoolean(context.getString(R.string.locationAlertsPref), false);

        // Is it enabled?
        if (!locationAlerts) {
            return false;
        }

        // Interval set to 0?
        if (getUpdateIntervalMilliseconds(context) == 0) {
            return false;
        }

        // We're good
        return true;
    }

    public static void saveLastKnownLocation(Context context, float latitude, float longitude) {
        // Get shared preferences
        SharedPreferences preferences = Singleton.getSharedPreferences(context);

        // Edit preferences
        android.content.SharedPreferences.Editor editor = preferences.edit();

        // Store lat & long
        editor.putFloat(context.getString(R.string.latitudePref), latitude);
        editor.putFloat(context.getString(R.string.longitudePref), longitude);

        // Commit changes
        editor.commit();
    }

    public static Location getLocation(Context context) {
        // Get shared preferences
        android.content.SharedPreferences preferences = Singleton.getSharedPreferences(context);

        // Edit preferences
        double latitude = preferences.getFloat(context.getString(R.string.latitudePref), 0);
        double longitude = preferences.getFloat(context.getString(R.string.longitudePref), 0);

        // No location stored?
        if (latitude == 0) {
            return GetLastKnownLocation(context);
        }

        // Prepare new location object
        Location location = new Location(LocationManager.PASSIVE_PROVIDER);

        // Set lat & long
        location.setLatitude(latitude);
        location.setLongitude(longitude);

        // Return it
        return location;
    }

    public static Location GetLastKnownLocation(Context context) {
        // Get location manager
        LocationManager locationManager = (LocationManager) context.getSystemService(context.LOCATION_SERVICE);

        // Create location criteria
        Criteria criteria = new Criteria();

        // Set fine accuracy
        criteria.setAccuracy(criteria.ACCURACY_FINE);

        // Get best provider
        String bestProvider = locationManager.getBestProvider(criteria, false);

        // No provider?
        if (bestProvider == null) {
            // Return null
            return null;
        }

        // No permission?
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return null;
        }

        // Return last location
        return locationManager.getLastKnownLocation(bestProvider);
    }
} public class LocationService extends Service implements
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        LocationListener {
    IBinder mServiceBinder;
    GoogleApiClient mClient;
    LocationRequest mLocationRequest;

    @Override
    public void onCreate() {
        super.onCreate();

        // Must have Google Play Services
        if (!GooglePlayServices.isAvailable(this)) {
            return;
        }

        // Check if the user revoked location access
        // Must have location permission to continue
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ||
                ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }

        // Initialize location polling
        initializeLocationPolling();

        // Initialize binder
        mServiceBinder = new LocalBinder();

        // Write to log
        Log.d(Logging.TAG, "LocationService started");
    }

    void initializeLocationPolling() {
        // Create new request
        mLocationRequest = LocationRequest.create();

        // Low battery mode
        mLocationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);

        // Set update intervals
        mLocationRequest.setInterval(LocationLogic.getUpdateIntervalMilliseconds(this));

        // Create new location receive client
        mClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
    }

    public void updateRequestInterval() {
        // Called when not requesting?
        if (mLocationRequest == null) {
            return;
        }

        // Set update intervals
        mLocationRequest.setInterval(LocationLogic.getUpdateIntervalMilliseconds(this));
    }

    void connectLocationClient() {
        // Got a location client?
        if (mClient != null) {
            // Client isn't already connected?
            if (!mClient.isConnected() || !mClient.isConnecting()) {
                // Ask for updates
                mClient.connect();
            }
        }
    }

    @Override
    public int onStartCommand(Intent Intent, int Flags, int StartId) {
        // Try connecting
        connectLocationClient();

        // Sticky service!
        return START_STICKY;
    }

    void disconnectClient() {
        // Got a client?
        if (mClient != null && mClient.isConnected()) {
            try {
                // Stop asking for updates
                LocationServices.FusedLocationApi.removeLocationUpdates(mClient, LocationService.this);

                // Disconnect client
                mClient.disconnect();
            }
            catch (Exception exc) {
                // Log to logcat
                Log.e(Logging.TAG, "LocationClient disconnect failed", exc);
            }
        }
    }

    void reconnect() {
        // First, try disconnecting
        disconnectClient();

        // Connect again
        connectLocationClient();
    }

    @Override
    public void onDestroy() {
        // Got a client?
        disconnectClient();

        // Now we're ready to be destroyed
        super.onDestroy();
    }

    @Override
    public void onLocationChanged(Location location) {
        // Get lat & long as float
        float latitude = (float) location.getLatitude();
        float longitude = (float) location.getLongitude();

        // Save to preferences
        LocationLogic.saveLastKnownLocation(this, latitude, longitude);

        // Reload nearby cities in case we're in the Location Alerts settings page
        Broadcasts.publish(this, LocationAlertsEvents.LOCATION_RECEIVED);

        // Write to log
        Log.d(Logging.TAG, "Location: " + latitude + "," + longitude);
    }

    @Override
    public void onConnected(Bundle dataBundle) {
        // No client?
        if (mClient == null || mLocationRequest == null) {
            return;
        }

        try {
            // Request updates
            LocationServices.FusedLocationApi.requestLocationUpdates(mClient, mLocationRequest, this);
        }
        catch (Exception exc) {
            // Log it
            Log.e(Logging.TAG, "FusedLocationApi connection failed", exc);

            // Try reconnecting
            reconnect();
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
        // Should we do something in this case?
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        // Try reconnecting
        reconnect();
    }

    @Override
    public IBinder onBind(Intent arg0) {
        // Provide service binder
        return mServiceBinder;
    }

    public class LocalBinder extends Binder {
        public LocationService getService() {
            // Return the instance
            return LocationService.this;
        }
    }
} public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
    private AppCompatDelegate mDelegate;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        getDelegate().installViewFactory();
        getDelegate().onCreate(savedInstanceState);
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        getDelegate().onPostCreate(savedInstanceState);
    }

    public ActionBar getSupportActionBar() {
        return getDelegate().getSupportActionBar();
    }

    public void setSupportActionBar(@Nullable Toolbar toolbar) {
        getDelegate().setSupportActionBar(toolbar);
    }

    @Override
    public MenuInflater getMenuInflater() {
        return getDelegate().getMenuInflater();
    }

    @Override
    public void setContentView(@LayoutRes int layoutResID) {
        getDelegate().setContentView(layoutResID);
    }

    @Override
    public void setContentView(View view) {
        getDelegate().setContentView(view);
    }

    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        getDelegate().setContentView(view, params);
    }

    @Override
    public void addContentView(View view, ViewGroup.LayoutParams params) {
        getDelegate().addContentView(view, params);
    }

    @Override
    protected void onPostResume() {
        super.onPostResume();
        getDelegate().onPostResume();
    }

    @Override
    protected void onTitleChanged(CharSequence title, int color) {
        super.onTitleChanged(title, color);
        getDelegate().setTitle(title);
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        getDelegate().onConfigurationChanged(newConfig);
    }

    @Override
    protected void onStop() {
        super.onStop();
        getDelegate().onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        getDelegate().onDestroy();
    }

    public void invalidateOptionsMenu() {
        getDelegate().invalidateOptionsMenu();
    }

    private AppCompatDelegate getDelegate() {
        if (mDelegate == null) {
            mDelegate = AppCompatDelegate.create(this, null);
        }
        return mDelegate;
    }
} public class AlertDialogBuilder {
    public static final void showGenericDialog(String title, String message, Context context, DialogInterface.OnClickListener clickListener) {
        // Use builder to create dialog
        AlertDialog.Builder builder = new AlertDialog.Builder(context);

        // Use builder to create dialog
        builder.setTitle(title).setMessage(message).setCancelable(false).setPositiveButton(R.string.okay, clickListener);

        // Prevent cancellation
        builder.setCancelable(false);

        try {
            // Build it
            AlertDialog dialog = builder.create();

            // Show it
            dialog.show();

            // Support for RTL languages
            RTLSupport.mirrorDialog(dialog, context);
        }
        catch (Exception exc) {
            // Show toast instead
            Toast.makeText(context, title + " - " + message, Toast.LENGTH_LONG).show();
        }
    }
} public class LocationDialogs {
    private static AlertDialog mLocationServicesDialog;

    public static void requestEnableLocationServices(final Activity context) {
        // Location alerts disabled?
        if (!AppPreferences.getLocationAlertsEnabled(context)) {
            return;
        }

        // Check permissions
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestLocationPermissionIfNecessary(context);
        }

        // Get location manager
        LocationManager locationManager = (LocationManager) context.getSystemService(context.LOCATION_SERVICE);

        // GPS enabled?
        if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            return;
        }

        // Network triangulation enabled?
        if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
            return;
        }

        // Already have a historical dialog?
        if (mLocationServicesDialog != null) {
            try {
                // Try to dismiss it
                mLocationServicesDialog.hide();
            }
            catch (Exception exc) {
                // The dialog is probably no longer valid
                mLocationServicesDialog = null;
            }
        }

        // Use builder to create dialog
        AlertDialog.Builder builder = new AlertDialog.Builder(context);

        // Use builder to create dialog
        builder.setTitle(context.getString(R.string.locationAlerts)).setMessage(context.getString(R.string.enableGPSDesc));

        // Set positive button
        builder.setPositiveButton(R.string.enable, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                // Display the GPS setting screen
                context.startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
            }
        });

        // Set negative button
        builder.setNegativeButton(R.string.notNow, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int i) {
                // Hide dialog
                dialog.dismiss();
            }
        });

        try {
            // Create the dialog
            mLocationServicesDialog = builder.create();

            // Show dialog
            mLocationServicesDialog.show();

            // Support for RTL languages
            RTLSupport.mirrorDialog(mLocationServicesDialog, context);

        }
        catch (Exception exc) {
            // Show toast instead
            Toast.makeText(context, context.getString(R.string.enableGPSDesc), Toast.LENGTH_LONG).show();
        }
    }

    private static void requestLocationPermissionIfNecessary(Activity context) {
        // Check if user hasn't yet granted permission
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ||
                ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // Display permission dialog
            ActivityCompat.requestPermissions(context,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
                    100);
        }
    }
} public class SliderPreference extends DialogPreference {

    protected final static int SEEKBAR_RESOLUTION = 10000;

    protected float mValue;
    protected int mSeekBarValue;
    protected CharSequence[] mSummaries;
    onSeekBarChangedListener seekBarChangedListener;

    /**
     * @param context
     * @param attrs
     */
    public SliderPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        setup(context, attrs);
    }

    /**
     * @param context
     * @param attrs
     * @param defStyle
     */
    public SliderPreference(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setup(context, attrs);
    }

    private void setup(Context context, AttributeSet attrs) {
        setDialogLayoutResource(R.layout.slider_preference_dialog);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SliderPreference);
        try {
            setSummary(a.getTextArray(R.styleable.SliderPreference_android_summary));
        }
        catch (Exception e) {
            // Do nothing
        }
        a.recycle();
    }

    @Override
    protected Object onGetDefaultValue(TypedArray a, int index) {
        return a.getFloat(index, 0);
    }

    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
        setValue(restoreValue ? getPersistedFloat(mValue) : (Float) defaultValue);
    }

    @Override
    public CharSequence getSummary() {
        if (mSummaries != null && mSummaries.length > 0) {
            int index = (int) (mValue * mSummaries.length);
            index = Math.min(index, mSummaries.length - 1);
            return mSummaries[index];
        }
        else {
            return super.getSummary();
        }
    }

    @Override
    @SuppressWarnings("ResourceType")
    public void setSummary(int summaryResId) {
        try {
            setSummary(getContext().getResources().getStringArray(summaryResId));
        }
        catch (Exception e) {
            super.setSummary(summaryResId);
        }
    }

    public void setSummary(CharSequence[] summaries) {
        mSummaries = summaries;
    }

    @Override
    public void setSummary(CharSequence summary) {
        super.setSummary(summary);
        mSummaries = null;
    }

    public float getValue() {
        return mValue;
    }

    public void setValue(float value) {
        value = Math.max(0, Math.min(value, 1)); // clamp to [0, 1]
        if (shouldPersist()) {
            persistFloat(value);
        }
        if (value != mValue) {
            mValue = value;
            notifyChanged();
        }
    }

    onSeekBarChangedListener getSeekBarChangedListener() {
        return seekBarChangedListener;
    }

    public void setSeekBarChangedListener(onSeekBarChangedListener listener) {
        seekBarChangedListener = listener;
    }

    public String getDialogMessage(float value) {
        if (getSeekBarChangedListener() == null) {
            return "?";
        }

        return getSeekBarChangedListener().getDialogMessage(value);
    }

    @Override
    protected View onCreateDialogView() {
        mSeekBarValue = (int) (mValue * SEEKBAR_RESOLUTION);
        View view = super.onCreateDialogView();

        final TextView message = (TextView) view.findViewById(android.R.id.message);
        final SeekBar seekbar = (SeekBar) view.findViewById(R.id.slider_preference_seekbar);

        seekbar.setMax(SEEKBAR_RESOLUTION);
        seekbar.setProgress(mSeekBarValue);
        seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }

            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (fromUser) {
                    SliderPreference.this.mSeekBarValue = progress;

                    reloadDialogSummary(message);
                }
            }
        });

        // Set initial summary
        reloadDialogSummary(message);

        return view;
    }

    void reloadDialogSummary(TextView message) {
        float newValue = (float) mSeekBarValue / SEEKBAR_RESOLUTION;

        String newMessage = getDialogMessage(newValue);

        message.setText(newMessage);
        setDialogMessage(newMessage);
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        final float newValue = (float) mSeekBarValue / SEEKBAR_RESOLUTION;
        if (positiveResult && callChangeListener(newValue)) {
            setValue(newValue);
        }
        super.onDialogClosed(positiveResult);
    }

    public interface onSeekBarChangedListener {
        String getDialogMessage(float value);
    }

    // TODO: Save and restore preference state.
} public class RTLSupport {
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    public static void mirrorActionBar(Activity activity) {
        // Hebrew only
        if (!Localization.isHebrewLocale(activity)) {
            return;
        }

        // Must be Jellybean or newer
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            // Set RTL layout direction
            activity.getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
        }
    }

    @SuppressLint("NewApi")
    public static void mirrorDialog(Dialog dialog, Context context) {
        // Hebrew only
        if (!Localization.isHebrewLocale(context)) {
            return;
        }

        try {
            // Get message text view
            TextView message = (TextView) dialog.findViewById(android.R.id.message);

            // Defy gravity
            if (message != null) {
                message.setGravity(Gravity.RIGHT);
            }

            // Get the title of text view
            TextView title = (TextView) dialog.findViewById(context.getResources().getIdentifier("alertTitle", "id", "android"));

            // Defy gravity
            title.setGravity(Gravity.RIGHT);

            // Get list view (may not exist)
            ListView listView = (ListView) dialog.findViewById(context.getResources().getIdentifier("select_dialog_listview", "id", "android"));

            // Check if list & set RTL mode
            if (listView != null) {
                listView.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
            }

            // Get title's parent layout
            LinearLayout parent = ((LinearLayout) title.getParent());

            // Get layout params
            LinearLayout.LayoutParams originalParams = (LinearLayout.LayoutParams) parent.getLayoutParams();

            // Set width to WRAP_CONTENT
            originalParams.width = LinearLayout.LayoutParams.WRAP_CONTENT;

            // Defy gravity
            originalParams.gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL;

            // Set layout params
            parent.setLayoutParams(originalParams);
        }
        catch (Exception exc) {
            // Log failure to logcat
            Log.d(Logging.TAG, "RTL failed", exc);
        }
    }
} public class Broadcasts {
    public static void subscribe(Context context, SharedPreferences.OnSharedPreferenceChangeListener listener) {
        // Listen for preference changes
        Singleton.getSharedPreferences(context).registerOnSharedPreferenceChangeListener(listener);
    }

    public static void unsubscribe(Context context, SharedPreferences.OnSharedPreferenceChangeListener listener) {
        // Unsubscribe from preference changes
        Singleton.getSharedPreferences(context).unregisterOnSharedPreferenceChangeListener(listener);
    }

    public static void publish(Context context, String property) {
        // Edit shared preferences
        SharedPreferences.Editor edit = Singleton.getSharedPreferences(context).edit();

        // Store current ms in settings with the given property,
        // so that listeners will be notified
        edit.putLong(property, System.currentTimeMillis());

        // Save and flush
        edit.commit();
    }
} public class Volume {
    public static void setVolumeKeysAction(Activity context) {
        // Set the appropriate alert stream
        context.setVolumeControlStream(Sound.STREAM_TYPE);
    }
} public class StringUtils {
    public static boolean stringIsNullOrEmpty(String inputString) {
        // String is null? return true
        if (inputString == null) {
            return true;
        }

        // String is empty? true
        if (inputString.trim().equals("")) {
            return true;
        }

        // String is not empty
        return false;
    }

    public static String implode(String separator, List<String> data) {
        // No data?
        if (data.size() == 0) {
            return "";
        }

        // Create temp StringBuilder
        StringBuilder builder = new StringBuilder();

        // Loop over list except last item
        for (int i = 0; i < data.size() - 1; i++) {
            // Append current item
            builder.append(data.get(i));

            // Append separator
            builder.append(separator);
        }

        // Add last item without separator
        builder.append(data.get(data.size() - 1));

        // Return string
        return builder.toString();
    }

    public static String regexMatch(String source, String compilePattern) {
        // Compile regex
        Pattern compiledPattern = Pattern.compile(compilePattern);

        // Match against source input
        Matcher matcher = compiledPattern.matcher(source);

        // Prepare match object
        String match = "";

        // Did we find anything?
        if (matcher.find()) {
            // Get first group
            match = matcher.group(1);
        }

        // Return match
        return match;
    }
} public class GooglePlayServices {
    public static boolean isAvailable(Context context) {
        // Get availability checker
        GoogleApiAvailability playServices = GoogleApiAvailability.getInstance();

        // Check whether services are available
        int result = playServices.isGooglePlayServicesAvailable(context);

        // Are we good?
        return result == ConnectionResult.SUCCESS;
    }
} public class LocationData {
    private static List<City> mCities;

    /*
    // Zone = דן 161
    // Zone Code = 161
    // City Name = תל אביב
    // City Countdown = 15 שניות
     */

    public static String[] getAllCityNames(Context context) {
        // Check for english locale
        boolean isHebrew = Localization.isHebrewLocale(context);

        // Get all city objects
        List<City> cities = getAllCities(context);

        // Prepare names array
        List<String> names = new ArrayList<>();

        // Loop over cities
        for (City city : cities) {
            // Hebrew?
            if (isHebrew) {
                // Add to list
                names.add(city.name);
            }
            else {
                // Add english name to list
                names.add(city.nameEnglish);
            }
        }

        // Return array
        return names.toArray(new String[names.size()]);
    }

    public static String[] getAllCityValues(Context context) {
        // Prepare cities array
        List<City> cities = getAllCities(context);

        // Prepare array
        List<String> values = new ArrayList<String>();

        // Loop over cities
        for (City city : cities) {
            // Add to list
            values.add(city.value);
        }

        // Return array
        return values.toArray(new String[values.size()]);
    }

    public static String[] getAllCityZones(Context context) {
        // Get user's locale
        boolean isHebrew = Localization.isHebrewLocale(context);

        // Prepare cities array
        List<City> cities = getAllCities(context);

        // Prepare array
        List<String> values = new ArrayList<String>();

        // Loop over cities
        for (City city : cities) {
            // Hebrew?
            if (isHebrew) {
                // Add to list
                values.add(city.zone);
            }
            else {
                // Add to list
                values.add(city.zoneEnglish);
            }
        }

        // Return array
        return values.toArray(new String[values.size()]);
    }

    public static List<City> getAllCities(Context context) {
        // Got it in cache?
        if (mCities != null) {
            return mCities;
        }

        // Initialize the list
        mCities = new ArrayList<>();

        try {
            // Open the cities.json for reading
            InputStream stream = context.getResources().openRawResource(R.raw.cities);

            // Create a buffered reader
            BufferedReader reader = new BufferedReader(new InputStreamReader(stream));

            // StringBuilder for efficiency
            StringBuilder builder = new StringBuilder();

            // A temporary variable to store current line
            String currentLine;

            // Read all lines
            while ((currentLine = reader.readLine()) != null) {
                // Append to builder
                builder.append(currentLine);
            }

            // Convert to string
            String json = builder.toString();

            // Convert to city objects
            mCities = Singleton.getJackson().readValue(json, new TypeReference<List<City>>() {
            });
        }
        catch (Exception exc) {
            // Log it
            Log.e(Logging.TAG, "Failed to load cities.json", exc);
        }

        // Return them
        return mCities;
    }

    public static String getSelectedCityNamesByValues(Context context, String selection, CharSequence[] names, CharSequence[] values) {
        // No value? All cities are selected
        if (StringUtils.stringIsNullOrEmpty(selection) || selection.equals(context.getString(R.string.all))) {
            return context.getString(R.string.allString);
        }

        // Value equals none | null?
        else if (selection.equals(context.getString(R.string.none)) || selection.equals(context.getString(R.string.nullString))) {
            return context.getString(R.string.noneString);
        }

        // Display names
        List<String> selectedCityNames = new ArrayList<String>();

        // Remove area code
        String[] selectedValues = selection.split("\\|");

        // Loop over values
        for (String selectedValue : selectedValues) {
            // Loop over values
            for (int i = 0; i < values.length; i++) {
                // Got the value?
                if (values[i].equals(selectedValue)) {
                    // Add the name to list
                    selectedCityNames.add(names[i].toString());
                }
            }
        }

        // Failed to find cities?
        if (selectedCityNames.size() == 0) {
            // Return "none"
            return context.getString(R.string.noneString);
        }

        // Implode into a CSV string
        String displayText = StringUtils.implode(", ", selectedCityNames);

        // Truncate if too long
        if (displayText.length() > 120) {
            displayText = displayText.substring(0, 120) + "...";
        }

        // Return display text
        return displayText;
    }

    public static String getLocalizedZoneWithCountdown(String cityName, Context context) {
        // Get user's locale
        boolean isHebrew = Localization.isHebrewLocale(context);

        // Prepare cities array
        List<City> cities = getAllCities(context);

        // Loop over cities
        for (City city : cities) {
            // Got a match?
            if (city.name.equals(cityName)) {
                // Hebrew?
                if (isHebrew) {
                    // Return area countdown
                    return city.zone + " (" + city.time + ")";
                }
                else {
                    // Return area countdown in English
                    return city.zoneEnglish  + " (" + city.timeEnglish + ")";
                }
            }
        }

        // No match
        return "";
    }

    public static int getCityCountdown(String cityName, Context context) {
        // Prepare cities array
        List<City> cities = getAllCities(context);

        // Loop over cities
        for (City city : cities) {
            // Got a match?
            if (city.name.equals(cityName)) {
                // Return countdown
                return city.countdown;
            }
        }

        // No match
        return 0;
    }

    public static String getLocalizedCityName(String cityName, Context context) {
        // Get user's locale
        boolean isHebrew = Localization.isHebrewLocale(context);

        // Hebrew?
        if (isHebrew) {
            return cityName;
        }

        // Prepare cities array
        List<City> cities = getAllCities(context);

        // Loop over cities
        for (City city : cities) {
            // Got a match?
            if (city.name.equals(cityName)) {
                // Return english name
                return city.nameEnglish;
            }
        }

        // No match
        return cityName;
    }

    public static City getCityByName(String cityName, Context context) {
        // Prepare cities array
        List<City> cities = getAllCities(context);

        // Loop over cities
        for (City city : cities) {
            // Got a match?
            if (city.name.equals(cityName)) {
                return city;
            }
        }

        // No match
        return null;
    }

    public static String getNearbyCityNames(Location myLocation, Context context) {
        // Get user's locale
        boolean isHebrew = Localization.isHebrewLocale(context);

        // Prepare cities array
        List<City> cities = getAllCities(context);

        // Output array
        List<String> cityNames = new ArrayList<>();

        // Calculate max distance
        double maxDistance = LocationLogic.getMaxDistanceKilometers(context, -1);

        // String is not empty
        for (City city : cities) {
            // Prepare new location
            Location location = new Location("");

            // Set lat & long
            location.setLatitude(city.latitude);
            location.setLongitude(city.longitude);

            // Get distance to city in KM
            float distance = location.distanceTo(myLocation) / 1000;

            // Distance is less than max?
            if (distance <= maxDistance) {
                // Hebrew?
                if (isHebrew) {
                    // Add to list
                    cityNames.add(city.name);
                }
                else {
                    // Add to list
                    cityNames.add(city.nameEnglish);
                }
            }
        }

        // Join and add original code
        return StringUtils.implode(", ", cityNames);
    }

    public static Location getCityLocation(String cityName, Context context) {
        // Prepare cities array
        List<City> cities = getAllCities(context);

        // Loop over cities
        for (City city : cities) {
            // Got a match?
            if (city.name.equals(cityName)) {
                // Prepare new location
                Location location = new Location(LocationManager.PASSIVE_PROVIDER);

                // Set lat & long
                location.setLatitude(city.latitude);
                location.setLongitude(city.longitude);

                // Add to list
                return location;
            }
        }

        // Fail
        return null;
    }

    public static List<String> explodeCitiesPSV(String citiesPSV) {
        // Unique cities list
        List<String> uniqueList = new ArrayList<>();

        // Explode into array
        List<String> psvList = Arrays.asList(citiesPSV.split("\\|"));

        // Loop over items
        for (String item : psvList) {
            // Not already added?
            if (!StringUtils.stringIsNullOrEmpty(item) && !uniqueList.contains(item) && !item.equals("none") && !item.equals("null")) {
                // Add it
                uniqueList.add(item);
            }
        }

        // Return them
        return uniqueList;
    }

    public static String getZoneByCityName(String cityName, Context context) {
        // Prepare cities array
        List<City> cities = getAllCities(context);

        // Loop over cities
        for (City city : cities) {
            // Got a match?
            if (city.name.equals(cityName)) {
                return city.zone;
            }
        }

        // Unknown city
        return "";
    }

    public static String getLocalizedZoneByCityName(String cityName, Context context) {
        // Get user's locale
        boolean isHebrew = Localization.isHebrewLocale(context);

        // Prepare cities array
        List<City> cities = getAllCities(context);

        // Loop over cities
        for (City city : cities) {
            // Got a match?
            if (city.name.equals(cityName)) {
                return isHebrew ? city.zone: city.zoneEnglish;
            }
        }

        // Unknown city
        return "";
    }
}
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.view.MenuItem;
import com.red.alert.R;
import com.red.alert.logic.communication.broadcasts.LocationAlertsEvents;
import com.red.alert.logic.location.LocationLogic;
import com.red.alert.services.location.LocationService;
import com.red.alert.ui.activities.AppCompatPreferenceActivity;
import com.red.alert.ui.dialogs.AlertDialogBuilder;
import com.red.alert.ui.dialogs.custom.LocationDialogs;
import com.red.alert.ui.elements.SliderPreference;
import com.red.alert.ui.localization.rtl.RTLSupport;
import com.red.alert.utils.communication.Broadcasts;
import com.red.alert.utils.feedback.Volume;
import com.red.alert.utils.formatting.StringUtils;
import com.red.alert.utils.integration.GooglePlayServices;
import com.red.alert.utils.metadata.LocationData;
package com.red.alert.activities.settings.alerts;



public class LocationAlerts extends AppCompatPreferenceActivity {
    Preference mNearbyCities;

    CheckBoxPreference mGPS;
    SliderPreference mFrequency;