package com.algobase.gpx;

import java.util.Locale;

import android.location.Location;

	
public class TrackPoint {

  static final int prec_location = 1000000; // 6 digits after dec point (11cm)
  static final int prec_dist_low = 10;   // dm
  static final int prec_dist_high = 100; // cm
  static final int prec_time = 1000;     // msec --> sec

  public int  id;
  public int time;
  public int lon;
  public int lat;
  public int alt;
  public int acc;
  public int dist;
  public int speed;
  public int ascent;
  public int hrate;
  public int power;
  public int cad;
  public int temp;

  private String format(String pattern, Object... args)
  { return String.format(Locale.US,pattern,args); }


  public TrackPoint(int i,long t,double lon,double lat,double alt, double acc, 
               double speed, double dist, double ascent,int hrate, int power,
               int cad, int temp)	
  { construct(i,t,lon,lat,alt,acc,speed,dist,ascent,hrate,power,cad,temp); }

  public TrackPoint(int i, Location loc, 
                           double dist, double ascent, int hrate, int power,
                           int cad, int temp)	
  { construct(i,loc.getTime(),
                loc.getLongitude(), 
                loc.getLatitude(),
                loc.getAltitude(),
                loc.getAccuracy(), 
                loc.getSpeed(), dist, ascent, hrate, power,cad,temp);
   }

  private void construct(int i,long t,double _lon,double _lat,double _alt,
                         double _acc, double _speed, double _dist, 
                         double _ascent, int _hrate, int _power,
                         int _cad, int _temp)	
  { id = i;
    time  = (int)Math.floor(0.5 + t/prec_time);
    lon   = (int)Math.floor(0.5 + prec_location  * _lon);
    lat   = (int)Math.floor(0.5 + prec_location  * _lat);
    alt   = (int)Math.floor(0.5 + prec_dist_low  * _alt);
    acc   = (int)Math.floor(0.5 + prec_dist_low  * _acc);
    ascent= (int)Math.floor(0.5 + prec_dist_low  * _ascent);
    speed = (int)Math.floor(0.5 + prec_dist_high * _speed);
    dist  = (int)Math.floor(0.5 + prec_dist_high * _dist);
    hrate = (_hrate < 0) ? 0 : _hrate;
    power = (_power < 0) ? 0 : _power;
    cad   = (_cad < 0)   ? 0 : _cad;
    temp  = (_temp < 0)  ? 0 : _temp;
   }

  public TrackPoint(int i, TrackPoint p, long t)	
  { id = i;
    time = p.time + (int)Math.floor(0.5 + t/prec_time);
    lon = p.lon;
    lat = p.lat;
    alt = p.alt;
    acc = p.acc;
    speed = p.speed;
    dist = p.dist;
    ascent = p.ascent;
    hrate = p.hrate;
    power = p.power;
    cad = p.cad;
    temp = p.temp;
   }


  public Location getLocation() {
     Location loc = new Location("gps");
     loc.setTime(get_time());
     loc.setLongitude(get_lon());
     loc.setLatitude(get_lat());
     loc.setAltitude(get_alt());
     loc.setAccuracy(get_accuracy());
     loc.setSpeed(get_speed());
     return loc;
  }

  public static String precision_comment_line() { 
    return "#prec_loc  prec_dist_high  prec_dist_low";
  }

  public static String precision_line() { 
    return "X" + prec_location + " " + prec_dist_high + " " + prec_dist_low;
  }

  public static String track_comment_line() { 
    return "#time lon lat alt spd dst asc hrt pwr cad temp";
  }

  public String trk_line() 
  { 
    return format("P%d %d %d %d %d %d %d %d %d %d %d", 
                   time,lon,lat,alt,speed,dist,ascent,hrate,power,cad,temp);
   }


  public String trk_line(TrackPoint q)
  {
    if (q == null) return trk_line();

    // write difference to q  (this - q)

    int t   = this.time  - q.time;
    int lon = this.lon   - q.lon;
    int lat = this.lat   - q.lat;
    int alt = this.alt   - q.alt;
    int acc = this.acc   - q.acc;
    int dst = this.dist  - q.dist;
    int spd = this.speed - q.speed;
    int asc = this.ascent- q.ascent;
    int hrt = this.hrate - q.hrate;
    int pwr = this.power - q.power;
    int cad = this.cad   - q.cad;
    int temp = this.temp  - q.temp;

    char p_type = (id == 0) ? 'D' : 'B'; // point or break

    String line = format("%c%d%+d%+d%+d%+d", p_type, t,lon,lat,alt,spd);

    if (temp != 0)
      line += format("%+d%+d%+d%+d%+d%+d",dst,asc,hrt,pwr,cad,temp);
    else
    if (cad != 0)
      line += format("%+d%+d%+d%+d%+d",dst,asc,hrt,pwr,cad);
    else
    if (pwr != 0)
      line += format("%+d%+d%+d%+d",dst,asc,hrt,pwr);
    else if (hrt != 0)
      line += format("%+d%+d%+d",dst,asc,hrt);
    else if (asc != 0)
      line += format("%+d%+d",dst,asc);
    else if (dst != 0)
      line += format("%+d",dst);

    return line;
  }
  

  public double get_lat() { return (double)lat/prec_location; }
  public double get_lon() { return (double)lon/prec_location; }

  public double get_alt()      { return (double)alt/prec_dist_low; }
  public double get_ascent()   { return (double)ascent/prec_dist_low; }
  public float  get_accuracy() { return (float)acc/prec_dist_low; }

  public double get_dist()  { return (double)dist/prec_dist_high; }
  public float  get_speed() { return (float)speed/prec_dist_high; }

  public long   get_time()  { return prec_time*(long)time; }
  public int    get_hrate() { return hrate; }
  public int    get_power() { return power; }

  public int    get_cadence()     { return cad; }
  public int    get_temperature() { return temp; }

}

