package com.algobase.gpx;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Locale;

import android.location.Location;

import com.algobase.stracks.sTracksRoot;

public class GpsReader {

   public void writeLog(String txt) {}

   public void handle_track_begin(String name, int length, int rec_mode) {}
   public void handle_track_end() {}
   public void handle_track_point(int i, Location loc,
                           double gps_alt,double srtm3_alt,double baro_alt, 
                           float dst, float spd, float press,
                           int hrt, int pwr, float cad, float tmp) {}

   public void handle_lap() {}
   public void handle_start(long t) {}
   public void handle_stop(long t) {}


   File gps_file;


   int point_num = 0;
   int pt_count = 0;
   int recording_mode = 0;

   String trk_name = "";
   String gps_line = "";

   int[] cal_points = new int[256];
   float[] cal_values = new float[256];
   int cal_count = 0;

   public GpsReader(File file) {
      gps_file = file;
   }

   public String getTrackName() { return trk_name; }
   public int getTrackLength() { return point_num; }


   void parse_line(String line)
   { 
/*
      if (line.charAt(0) == '#') {
        if (line.equals("#lap")) handle_lap();
        return;
      }
*/
     int p = 0; 
     int q = -1;

     long t = 0;
     double lon = 0;
     double lat = 0;
     float  acc = 0;
     double alt = 0;
     double gps_alt = 0;
     double srtm3_alt = 0;
     double baro_alt = 0;
     float dst = 0;
     float spd = 0;
     float press = 0;
     int   hrate = 0;
     int   power = 0;
     float cad = 0;
     float tmp = -100;

// parse data line
// t lon lat alt acc gps_alt srtm3_alt baro_alt dst spd prs hrt pwr cad tmp

     try {

        p = q+1;
        if ((q = line.indexOf(" ",p)) == -1) return;
        t = Long.parseLong(line.substring(p,q));

        p = q+1;
        if ((q = line.indexOf(" ",p)) == -1) return;
        lon = Double.parseDouble(line.substring(p,q));

        p = q+1;
        if ((q = line.indexOf(" ",p)) == -1) return;
        lat = Double.parseDouble(line.substring(p,q));

        p = q+1;
        if ((q = line.indexOf(" ",p)) == -1) return;
        alt = Double.parseDouble(line.substring(p,q));

        p = q+1;
        if ((q = line.indexOf(" ",p)) == -1) return;
        acc = Float.parseFloat(line.substring(p,q));

        p = q+1;
        if ((q = line.indexOf(" ",p)) == -1) return;
        gps_alt = Double.parseDouble(line.substring(p,q));

        p = q+1;
        if ((q = line.indexOf(" ",p)) == -1) return;
        srtm3_alt = Double.parseDouble(line.substring(p,q));

        p = q+1;
        if ((q = line.indexOf(" ",p)) == -1) return;
        baro_alt = Double.parseDouble(line.substring(p,q));

        // calibration correction

        if (cal_count > 0) 
        { int i = 0;
          while (i < cal_count && pt_count >= cal_points[i]) i++;

          if (i < cal_count) 
          { int last = (i > 0) ? cal_points[i-1] : 0;
            int length = cal_points[i]-last;
            float delta = cal_values[i]/length;
            baro_alt += (pt_count-last)*delta;
           }
         }

        if (baro_alt == sTracksRoot.DISTANCE_UNDEFINED) baro_alt = alt;

        p = q+1;
        if ((q = line.indexOf(" ",p)) == -1) return;
        dst = Float.parseFloat(line.substring(p,q));

        p = q+1;
        if ((q = line.indexOf(" ",p)) == -1) return;
        spd = Float.parseFloat(line.substring(p,q));

        p = q+1;
        if ((q = line.indexOf(" ",p)) == -1) return;
        press = Float.parseFloat(line.substring(p,q));

        p = q+1;
        if ((q = line.indexOf(" ",p)) == -1) return;
        hrate = Integer.parseInt(line.substring(p,q));

        p = q+1;
        q = line.indexOf(" ",p);
        if (q == -1) q = line.length();
        power = Integer.parseInt(line.substring(p,q));

        p = q+1;
        q = line.indexOf(" ",p);
        if (q == -1) q = line.length();
        cad = Float.parseFloat(line.substring(p,q));

        p = q+1;
        q = line.indexOf(" ",p);
        if (q == -1) q = line.length();
        tmp = Float.parseFloat(line.substring(p,q));


     } catch(Exception e) { writeLog(e.toString()); }

     if (power > 2000) power = 0;

     if (acc < 0) {
      // invalid location
      return;
     }
 
     Location loc = new Location("gps");
     loc.setTime(t);
     loc.setLongitude(lon);
     loc.setLatitude(lat);
     loc.setAltitude(alt);
     loc.setAccuracy(acc);
     loc.setSpeed(spd);

     handle_track_point(pt_count,loc,gps_alt,srtm3_alt,baro_alt,dst,spd,press,
                        hrate, power, cad, tmp);
     pt_count++;
   }


    public String readTrackName()
    { trk_name = "";
      try {
         BufferedReader reader = new BufferedReader(new FileReader(gps_file));
         trk_name = reader.readLine();
         reader.close();
       } catch (IOException ex) { writeLog("exception: " + ex.toString()); }

      return trk_name;
    }


    public void read()
    {
      writeLog("");
      writeLog("GpsReader");
      writeLog(gps_file.getPath());

      // read calibrations

      cal_count = 0;

      try {
          BufferedReader reader = new BufferedReader(new FileReader(gps_file));

          trk_name = reader.readLine();
          gps_line = reader.readLine();

          point_num = 0;
          String line = reader.readLine();
          while (line != null && cal_count < 256)
          { if (line.startsWith("#calibration"))
            { // "#calibration value"
              String[] A = line.split(" ");
              cal_points[cal_count] = point_num;
              cal_values[cal_count] = Float.parseFloat(A[1]);
              cal_count++;
             }
            else
              if (!line.startsWith("#")) point_num++;
            line = reader.readLine();
           }

          reader.close();
       } catch (IOException ex) { writeLog("exception: " + ex.toString()); }


       writeLog("name = " + trk_name);
       writeLog("gps_line = " + gps_line);

       writeLog("");
       writeLog("CALIBRATIONS: " + cal_count);
       for(int i=0; i<cal_count; i++) {
         writeLog(String.format("point: %5d  value: %5.1f",cal_points[i],cal_values[i]));
       }
       writeLog("");


       if (gps_line.equals("gps:disabled"))
         recording_mode = 0;
       else
         recording_mode = 1;

       handle_track_begin(trk_name,point_num,recording_mode);

       int count = 0;

       try {
         FileReader file_reader = new FileReader(gps_file);
         BufferedReader reader = new BufferedReader(file_reader);
         reader.readLine(); // skip first line (name)
         reader.readLine(); // skip second line (gps line)

         String line = reader.readLine();

         while (line != null)
         { 
           if (line.length() > 0)
           { 
             if (line.charAt(0) == '#') 
              { // comment

                if (line.startsWith("#lap")) handle_lap();

                if (line.startsWith("#stop")) {
                  String s = line.replace("#stop","").trim();
                  handle_stop(Long.parseLong(s));
                }

                if (line.startsWith("#start")) {
                  String s = line.replace("#start","").trim();
                  handle_start(Long.parseLong(s));
                }
             }
             else 
                parse_line(line);
            }

           line = reader.readLine();

         } 

         file_reader.close();

       } catch (IOException e) { writeLog(e.toString()); }


       handle_track_end();
   }

}
