package com.algobase.ascent;

import com.algobase.stracks.sTracksRoot;

public class TotalAscent  {

  static final double DISTANCE_UNDEFINED = sTracksRoot.DISTANCE_UNDEFINED;

  public static final int ASCENT_NUM = 3;

  // 0: gps   1: srtm3   2: baro

//public static final float[] ASCENT_EPS = { 12.00f,  10.00f, 2.50f }; // 2.16
//public static final float[] ASCENT_EPS = { 15.00f,  12.50f, 3.00f }; // 2.22
//public static final float[] ASCENT_EPS = { 15.00f,  12.50f, 3.10f }; // 2.222
//public static final float[] ASCENT_EPS = { 15.00f,  12.50f, 3.25f }; // 2.223
//public static final float[] ASCENT_EPS = { 15.00f,  12.50f, 3.40f }; // 2.224
//public static final float[] ASCENT_EPS = { 15.00f,  12.50f, 3.00f }; // 2.225

  public static final float[] ASCENT_EPS = { 15.00f,  12.50f, 1.50f }; // 2.229


  public void writeLog(String txt) {}


  double ascent_eps = 1.0;
  double min_dist = 5.0;

  double[] total_ascent = new double[ASCENT_NUM];
  double[] total_descent = new double[ASCENT_NUM];
  double[] current_slope = new double[ASCENT_NUM];

  double[] last_ascent_alt = new double[ASCENT_NUM];
  double[] last_ascent_dist = new double[ASCENT_NUM];

  boolean[] ascending = new boolean[ASCENT_NUM];


  public void setAscentEps(double eps) { ascent_eps = eps; }
  public void setMinDist(double d) { min_dist = d; }

  public void reset(int k) {
    last_ascent_alt[k] = DISTANCE_UNDEFINED;
    last_ascent_dist[k] = 0;
    total_ascent[k] = 0;
    total_descent[k] = 0;
    current_slope[k] = 0;
  }

  public void reset() {
    for(int k=0; k < ASCENT_NUM; k++) reset(k);
  }

  public TotalAscent() {
    ascent_eps = 1.0;
    min_dist = 5.0;
    reset();
  }

  
  public double getAscent(int k) { return total_ascent[k]; }
  public double getDescent(int k) { return total_descent[k]; }
  public double getSlope(int k) { return current_slope[k]; }


  public void update0(int k, double alt, double dist, double acc)
  {
    double eps = ascent_eps * ASCENT_EPS[k];

    if (alt == DISTANCE_UNDEFINED) return;

    if (last_ascent_alt[k] == DISTANCE_UNDEFINED) 
    { last_ascent_alt[k] = alt;
      last_ascent_dist[k] = dist;
      return;
     }

    double diff_dist = dist - last_ascent_dist[k];

    double dmin = acc;
    if (min_dist > dmin) dmin = min_dist;
    if (diff_dist < dmin) return;

    double diff_alt  = alt - last_ascent_alt[k];

    double slope = diff_alt/diff_dist;

    if (Math.abs(slope) < 0.25) 
      current_slope[k] = (current_slope[k] + slope)/2;

    if (Math.abs(diff_alt) >= eps && Math.abs(slope) < 0.5)
    {
      if (diff_alt > 0) total_ascent[k] += diff_alt;
      if (diff_alt < 0) total_descent[k] -= diff_alt;

      last_ascent_alt[k]  = alt;
      last_ascent_dist[k] = dist;
    }
  }



  public void update(int k, double alt, double dist, double acc)
  {
    double eps = ascent_eps * ASCENT_EPS[k];

    if (alt == DISTANCE_UNDEFINED) return;

    if (last_ascent_alt[k] == DISTANCE_UNDEFINED) 
    { last_ascent_alt[k] = alt;
      last_ascent_dist[k] = dist;
      ascending[k] = false;
      return;
     }

    double diff_dist = dist - last_ascent_dist[k];

    double dmin = acc;
    if (min_dist > dmin) dmin = min_dist;
    if (diff_dist < dmin) return;

    double diff_alt  = alt - last_ascent_alt[k];

    double slope = diff_alt/diff_dist;

    if (Math.abs(slope) > 0.5) return; // artefact 

    current_slope[k] = (current_slope[k] + slope)/2;

    if (ascending[k])
    { 
      if (diff_alt > 0)
      { total_ascent[k] += diff_alt;
        last_ascent_alt[k]  = alt;
        last_ascent_dist[k] = dist;
       }
      else
      if (diff_alt <= -eps)
      { 
/*
        if (k == 2)
          writeLog(String.format("DESCENT: %.1f km  %.1f/%.1f m", 
                                                    last_ascent_dist[k]/1000, 
                                                    last_ascent_alt[k],
                                                    alt));
*/
        ascending[k] = false;
        total_descent[k] -= diff_alt;
        last_ascent_alt[k]  = alt;
        last_ascent_dist[k] = dist;
      }
    }
    else
    { // descending        
      if (diff_alt < 0)
      { total_descent[k] -= diff_alt;
        last_ascent_alt[k]  = alt;
        last_ascent_dist[k] = dist;
       }
      else
      if (diff_alt >= +eps)
      { 
/*
        if (k == 2)
          writeLog(String.format("ASCENT:  %.1f km  %.1f/%.1f m", 
                                                    last_ascent_dist[k]/1000, 
                                                    last_ascent_alt[k],
                                                    alt));
*/
        ascending[k] = true;
        total_ascent[k] += diff_alt;
        last_ascent_alt[k]  = alt;
        last_ascent_dist[k] = dist;
       }
    }

  }

}

