gt:             hours = seconds / 3600;
context: /*
   * Copyright (C) 2013 jonas.oreland@gmail.com
   *
   *  This program is free software: you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation, either version 3 of the License, or
   *  (at your option) any later version.
   *
   *  This program is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  
  package org.runnerup.util;
  
  import android.annotation.TargetApi;
  import android.content.Context;
  import android.content.SharedPreferences;
  import android.content.SharedPreferences.Editor;
  import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
  import android.content.res.Configuration;
  import android.content.res.Resources;
  import android.os.Build;
  import android.preference.PreferenceManager;
  import android.text.format.DateUtils;
  import android.util.Log;
  
  import org.runnerup.R;
  import org.runnerup.workout.Dimension;
  
  import java.text.DecimalFormat;
  import java.util.Locale;
  
  @TargetApi(Build.VERSION_CODES.FROYO)
  public class Formatter implements OnSharedPreferenceChangeListener {
  
      Context context = null;
      Resources resources = null;
      LocaleResources cueResources = null;
      SharedPreferences sharedPreferences = null;
      java.text.DateFormat dateFormat = null;
      java.text.DateFormat timeFormat = null;
      HRZones hrZones = null;
  
      boolean km = true;
      String base_unit = "km";
      double base_meters = km_meters;
  
      public final static double km_meters = 1000.0;
      public final static double mi_meters = 1609.34;
      public final static double FEETS_PER_METER = 3.2808;
  
      public static final int CUE = 1; // for text to speech
      public static final int CUE_SHORT = 2; // brief for tts
      public static final int CUE_LONG = 3; // long for tts
      public static final int TXT = 4; // same as TXT_SHORT but without unit
      public static final int TXT_SHORT = 5; // brief for printing
      public static final int TXT_LONG = 6; // long for printing
  
      public Formatter(Context ctx) {
          context = ctx;
          resources = ctx.getResources();
          cueResources = getLangResources(ctx);
          sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ctx);
          sharedPreferences.registerOnSharedPreferenceChangeListener(this);
  
          dateFormat = android.text.format.DateFormat.getDateFormat(ctx);
          timeFormat = android.text.format.DateFormat.getTimeFormat(ctx);
          hrZones = new HRZones(context);
  
          setUnit();
      }
  
      private class LocaleResources {
          final Resources resources;
          final Configuration configuration;
          final Locale defaultLocale;
          final Locale audioLocale;
  
          LocaleResources(Context ctx, Locale locale) {
              resources = ctx.getResources();
              configuration = resources.getConfiguration();
              defaultLocale = configuration.locale;
              audioLocale = locale;
          }
  
          void setLang(Locale locale) {
              configuration.locale = locale;
              resources.updateConfiguration(configuration, resources.getDisplayMetrics());
          }
  
          public String getString(int id) throws Resources.NotFoundException {
              setLang(audioLocale);
              String result = resources.getString(id);
              setLang(defaultLocale);
              return result;
          }
  
          public String getQuantityString(int id, int quantity) throws Resources.NotFoundException {
              setLang(audioLocale);
              String result = resources.getQuantityString(id, quantity);
              setLang(defaultLocale);
              return result;
          }
      };
  
      public static Locale getAudioLocale(Context ctx) {
          Resources res = ctx.getResources();
          SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
          if (prefs.contains(res.getString(R.string.pref_audio_lang))) {
              Log.e("Formatter", "Audio language: " +
                      prefs.getString(res.getString(R.string.pref_audio_lang), null));
              return new Locale(prefs.getString(res.getString(R.string.pref_audio_lang), "en"));
          }
          return null;
      }
  
      private LocaleResources getLangResources(Context ctx) {
          Locale loc = getAudioLocale(ctx);
          if (loc != null) {
              return new LocaleResources(ctx,loc);
          } else {
              return new LocaleResources(ctx, ctx.getResources().getConfiguration().locale);
          }
      }
  
      public String getCueString(int msgId) {
          return cueResources.getString(msgId);
      }
  
      @Override
      public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
              String key) {
          if (key != null && context.getString(R.string.pref_unit).contentEquals(key))
              setUnit();
      }
  
      private void setUnit() {
          km = getUseKilometers(context.getResources(), sharedPreferences, null);
  
          if (km) {
              base_unit = "km";
              base_meters = km_meters;
          } else {
              base_unit = "mi";
              base_meters = mi_meters;
          }
      }
  
      public static boolean getUseKilometers(Resources res, SharedPreferences prefs, Editor editor) {
          boolean _km = true;
          String unit = prefs.getString(res.getString(R.string.pref_unit), null);
          if (unit == null)
              _km = guessDefaultUnit(res, prefs, editor);
          else if (unit.contentEquals("km"))
              _km = true;
          else if (unit.contentEquals("mi"))
              _km = false;
          else
              _km = guessDefaultUnit(res, prefs, editor);
  
          return _km;
      }
  
      private static boolean guessDefaultUnit(Resources res, SharedPreferences prefs, Editor editor) {
          String countryCode = Locale.getDefault().getCountry();
          Log.e("Formatter", "guessDefaultUnit: countryCode: " + countryCode);
          if (countryCode == null)
              return true; // km;
          String key = res.getString(R.string.pref_unit);
          if ("US".contentEquals(countryCode) ||
                  "GB".contentEquals(countryCode)) {
              if (editor != null)
                  editor.putString(key, "mi");
              return false;
          }
          else {
              if (editor != null)
                  editor.putString(key, "km");
          }
          return true;
      }
  
      public double getUnitMeters() {
          return this.base_meters;
      }
  
      public static double getUnitMeters(Resources res, SharedPreferences prefs) {
          if (getUseKilometers(res, prefs, null))
              return km_meters;
          else
              return mi_meters;
      }
  
      public String getUnitString() {
          return this.base_unit;
      }
  
      public String format(int target, Dimension dimension, double value) {
          switch (dimension) {
              case DISTANCE:
                  return formatDistance(target, Math.round(value));
              case TIME:
                  return formatElapsedTime(target, Math.round(value));
              case PACE:
                  return formatPace(target, value);
              case HR:
                  return formatHeartRate(target, value);
              case HRZ:
                  return formatHeartRateZone(target, value);
              case SPEED:
                  return formatSpeed(target, value);
          }
          return "";
      }
  
      public String formatElapsedTime(int target, long seconds) {
          switch (target) {
              case CUE:
              case CUE_SHORT:
                  return cueElapsedTime(seconds, false);
              case CUE_LONG:
                  return cueElapsedTime(seconds, true);
              case TXT:
              case TXT_SHORT:
                  return DateUtils.formatElapsedTime(seconds);
              case TXT_LONG:
                  return txtElapsedTime(seconds);
          }
          return "";
      }
  
      private String cueElapsedTime(long seconds, boolean includeDimension) {
          long hours = 0;
          long minutes = 0;
          if (seconds >= 3600) {
  