package com.algobase.server;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Locale;
import java.util.ArrayList;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;

import com.algobase.share.network.*;


public class sTracksClient {

  public void write_log(String s) {}
  public void acknowledge_dialog(String s) {}
  
  private Context context;
  
  private String host;
  private String user;
  private String password;

  private int port;
  private int timeout;
  private float client_version;
  private String client_string;

  private String error_msg;

  private LedaSocket sock;

  private String format(String pattern, Object... args)
   { String s = "";
     try { s = String.format(Locale.US,pattern,args); 
     } catch (Exception e) {}
     return s;
   }

  
  public sTracksClient(Context c, LedaSocket s, float version) 
  { context = c;
    timeout = 3000;
    //sock = (s != null) ? s : new LedaSocket();
    sock = s;
    if (sock != null) sock.setTimeout(timeout);
    client_version = version;
    client_string = format("A%.3f",client_version);
  }

  public sTracksClient(Context c, String h, int p, float version) 
  { context = c;
    host = h;
    port = p;
    timeout = 3000;
    sock = null;
    client_version = version;
    client_string = format("A%.3f",client_version);
/*
    sock = new LedaSocket();  
    sock.setTimeout(timeout);
*/
   }

  public void set_socket(LedaSocket s) 
  { sock = s; 
    sock.setTimeout(timeout);
   }

  public void set_timeout(int t) 
  { timeout = t;
    if (sock != null) sock.setTimeout(timeout);
   }

  public void set_host(String s) { host = s; }
  public void set_port(int p)    { port = p; }
  public void set_user(String s) { user = s; }
  public void set_password(String s) { password = s; }

  public void set_client_version(float version) 
  { client_version = version;
    client_string = String.format("A%.3f",version); 
   }

  public String get_error() { return error_msg; }

  public int connect()
  { 
    write_log("sTracksClient::connect  " + host + ":" + port);

    if (sock == null)
    { sock = new LedaSocket();  
      sock.setTimeout(timeout);
     }

    if (!sock.connect(host,port))
    { error_msg = String.format("%s:%d  %s ",host,port,sock.getError());
      write_log(error_msg);
      //acknowledge_dialog(error_msg);
      acknowledge_dialog("No network connection.");
      return 1; 
     }

    write_log("connect: ok");

    String s = "";

    write_log("socket: receive random r");
    
    int r = sock.receiveInt();

    if (r == 0)
    { error_msg = "Network Problem:\nConnection Timeout";
      write_log(error_msg);
      acknowledge_dialog(error_msg);
      return 1; 
     }
     
    sock.sendInt(0);
    sock.wait("ok");

    write_log("send login string");

   String login = "login:" + client_string + ":" + user + ":" + password;

   sock.sendString(login);
   s = sock.receiveString();

   if (s.startsWith("ok:"))
      write_log("server version: " + s.substring(3));
   else
   { error_msg = "server error: " + s;
     acknowledge_dialog("Invalid user or password.");
     write_log(error_msg);
     sock.disconnect();
     sock = null;
     return 2; // unknown user
    }

    return 0;

/*
    write_log("send client version");

    sock.sendString(client_string);

    s = sock.receiveString();
    write_log("server version: " + s);

    sock.sendString(user);
    s = sock.receiveString();

    if (!s.equals("ok"))
    { error_msg = "server error: " + s;
      acknowledge_dialog("Invalid user.");
      write_log(error_msg);
      sock.disconnect();
      sock = null;
      return 2; // unknown user
     }

    sock.sendString(password);
    s = sock.receiveString();

    if (!s.equals("ok"))
    { error_msg = "server error: " + s;
      acknowledge_dialog("Invalid password.");
      write_log(error_msg);
      sock.disconnect();
      sock = null;
      return 3; // incorrect password
     }

    return 0;
*/
  }


  public void disconnect()
  { if (sock == null) return;
    sock.disconnect();
    sock = null;
  }


  public ArrayList<String> get_course_list(boolean dist) {
     return get_track_or_course_list(1,dist);
  }


  public ArrayList<String> get_track_list(boolean dist) { 
     return get_track_or_course_list(0,dist);
  }



  public ArrayList<String> get_track_or_course_list(int what, boolean dist)
  { 
     // what  0 : tracks  /  1 : courses

     ArrayList<String> L = new ArrayList<String>();

     String cmd = dist ? "list-dist" : "list";

     //if (what == 1) cmd = "list-routes";
     if (what == 1) cmd = "list-routes-android";

     write_log("send: " + cmd);
     sock.sendString(cmd);

     sock.wait("ok");
     sock.sendString("ok");

     File tmp = new File(context.getCacheDir(),"tmp");

     sock.receiveFile(tmp);

     sock.sendString("exit");
   //sock.wait("done");
     sock.disconnect();
     sock = null;

     try {
       BufferedReader in = new BufferedReader(new FileReader(tmp));
       String line = in.readLine();
       while (line != null)
       { L.add(line);
         line = in.readLine();
       }
       in.close();
     } catch (IOException e) {}
                
     return L;
  }


  public boolean receive_wpt(File file)
  { 
     write_log("send:  getall-wpt");
     sock.sendString("getall-wpt");

     error_msg = sock.receiveString();
     write_log("success = " + error_msg);

     boolean success = false;

     if (error_msg.equals("ok")) 
     { sock.sendString("ok");
       sock.receiveFile(file);
       success = true;
      }

     sock.sendString("exit");
     write_log("disconnect");
     sock.disconnect();
     sock = null;
     return success;
   }

  public boolean send_wpt(File file)
  { File[] files = new File[1];
    files[0] = file;
    return send_wpt(files);
   }


  public boolean send_wpt(File[] files)
  { 
    if (files.length == 0) return true;

    String cmd = "put-wpt";

    write_log("send: " + cmd);
    sock.sendString(cmd);

    sock.wait("ok");
    sock.sendFiles(files);
    error_msg = sock.receiveString();
    write_log("success = " + error_msg);
    sock.sendString("exit");
    write_log("disconnect");
    sock.disconnect();
    sock = null;
    return error_msg.equals("ok");
  }

  public boolean send_trk(File file)
  { File[] files = new File[1];
    files[0] = file;
    return send_trk(files);
  }

  public boolean send_trk(File[] files)
  { 
    if (files.length == 0) return true;

    String cmd = "put-trk";

    write_log("send: " + cmd);
    sock.sendString(cmd);

    sock.wait("ok");
    sock.sendFiles(files);
    error_msg = sock.receiveString();
    write_log("success = " + error_msg);
    sock.sendString("exit");
    write_log("disconnect");
    sock.disconnect();
    sock = null;
    return error_msg.equals("ok");
  }


  public boolean send_crs(File file)
  { File[] files = new File[1];
    files[0] = file;
    return send_crs(files);
  }

  public boolean send_crs(File[] files)
  { 
    if (files.length == 0) return true;

    String cmd = "put-routes-trk";

    write_log("send: " + cmd);
    sock.sendString(cmd);

    sock.wait("ok");
    sock.sendFiles(files);
    error_msg = sock.receiveString();
    write_log("success = " + error_msg);
    sock.sendString("exit");
    write_log("disconnect");
    sock.disconnect();
    sock = null;
    return error_msg.equals("ok");
  }


  public boolean send_gpx(File[] files)
  { 
    if (files.length == 0) return true;

    String cmd = "put-gpx";

    SensorManager sm = 
       (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);

     write_log("send: " + cmd);
     sock.sendString(cmd);

     sock.wait("ok");
     sock.sendFiles(files);
     error_msg = sock.receiveString();
     write_log("success = " + error_msg);
     sock.sendString("exit");
     write_log("disconnect");
     sock.disconnect();
     sock = null;
     return error_msg.equals("ok");
   }

  public boolean receive_trk(File file, String name)
  { 
     write_log("send:  get-trk");
     sock.sendString("get-trk");
     sock.wait("ok");
     sock.sendString(name);  // list
     sock.sendString("end");
     error_msg = sock.receiveString();
     write_log("success = " + error_msg);
     boolean success = error_msg.equals("ok");
     if (success) sock.receiveFile(file);
     sock.sendString("exit");
     write_log("disconnect");
     sock.disconnect();
     sock = null;
     return success;
   }


  public boolean receive_course(File file, String name)
  { 
     write_log("send:  get-routes-trk");
     sock.sendString("get-routes-trk");
     sock.wait("ok");
     sock.sendString(name);  // list
     sock.sendString("end");

     error_msg = sock.receiveString();
     write_log("success = " + error_msg);
     boolean success = error_msg.equals("ok");
     if (success) sock.receiveFile(file);
     sock.sendString("exit");
     write_log("disconnect");
     sock.disconnect();
     sock = null;
     return success;
   }



  public boolean receive_gpx(File file, String name)
  { 
     write_log("send:  get-gpx");
     sock.sendString("get-gpx");
     sock.wait("ok");
     sock.sendString(name);  // list
     sock.sendString("end");
     error_msg = sock.receiveString();
     write_log("success = " + error_msg);
     boolean success = error_msg.equals("ok");
     if (success) sock.receiveFile(file);
     sock.sendString("exit");
     write_log("disconnect");
     sock.disconnect();
     sock = null;
     return success;
   }

  public boolean receive_srtm3(File dir, String name)
  { 
     write_log("receive_srtm3: " + name);

     File file = new File(dir,name);

     sock.sendString("get-srtm3");
     sock.wait("ok");
     sock.sendString(name); 
     error_msg = sock.receiveString();
     write_log("success = " + error_msg);

     boolean success = false;

     if (error_msg.equals("ok")) 
     { sock.sendString("ok");
       sock.receiveFile(file); 
       success = true;
      }

     sock.sendString("exit");
     write_log("disconnect");
     sock.disconnect();
     sock = null;
     return success;
   }

  public boolean receive_file(File file, String name)
  { 
     write_log("receive_file: " + name);

     sock.sendString("send-file");
     sock.wait("ok");
     sock.sendString(name); 
     error_msg = sock.receiveString();
     write_log("success = " + error_msg);

     boolean success = false;

     if (error_msg.equals("ok")) 
     { sock.sendString("ok");
       sock.receiveFile(file); 
       success = true;
      }

     sock.sendString("exit");
     write_log("disconnect");
     sock.disconnect();
     sock = null;
     return success;
   }



  public boolean delete_waypoint(String name)
  {    	 
     write_log("client: delete " + name);
     
     sock.sendString("del-waypoints");
     sock.wait("ok");   
     sock.sendString(name);
     boolean result = sock.wait("ok");
     write_log("success = " + result);
     sock.sendString("end");     
     sock.sendString("exit");
     //sock.wait("done");
     write_log("disconnect");
     sock.disconnect();
     sock = null;
     return result;
   }

  public boolean delete_track(String name)
  {    	 
     write_log("client: delete " + name);
     
     sock.sendString("del");
     sock.wait("ok");   
     sock.sendString(name);
     boolean result = sock.wait("ok");
     write_log("success = " + result);
     sock.sendString("end");     
     sock.sendString("exit");
     //sock.wait("done");
     write_log("disconnect");
     sock.disconnect();
     sock = null;
     return result;
   }

  public boolean delete_course(String name)
  {    	 
     write_log("client: delete " + name);
     
     sock.sendString("del-routes");
     sock.wait("ok");   
     sock.sendString(name);
     boolean result = sock.wait("ok");
     write_log("success = " + result);
     sock.sendString("end");     
     sock.sendString("exit");
     //sock.wait("done");
     write_log("disconnect");
     sock.disconnect();
     sock = null;
     return result;
   }


  public boolean check_password()
  { write_log("client: check password");
    sock.sendString("check-passwd");
    String s = sock.receiveString();
    write_log("s = " + s);
    sock.sendString("exit");
    //sock.wait("done");
    write_log("disconnect");
    sock.disconnect();
    sock = null;
    return s.equals("ok");
  }


  public void send_password(String pwd)
  { write_log("client: set password");
    sock.sendString("passwd");
    sock.wait("ok");   
    sock.sendString(pwd);
    sock.wait("ok");   
    sock.sendString("exit");
    //sock.wait("done");
    write_log("disconnect");
    sock.disconnect();
    sock = null;
  }

  public void create_password()
  { write_log("client: create password");
    sock.sendString("create-passwd");
    sock.wait("ok");   
    sock.sendString("ok");
    sock.sendString("exit");
    //sock.wait("done");
    write_log("disconnect");
    sock.disconnect();
    sock = null;
  }

  public String get_email_address()
  { write_log("client: get email");
    sock.sendString("send-email");
    sock.wait("ok");   
    sock.sendString("ok");
    String s = sock.receiveString();   
    sock.sendString("exit");
    //sock.wait("done");
    write_log("disconnect");
    sock.disconnect();
    sock = null;
    return s;
  }

  public boolean send_strava_token(String token)
  { 
    String cmd = "strava-token";

    write_log("send strava token");
    sock.sendString(cmd);

    sock.wait("ok");
    sock.sendString(token);
    error_msg = sock.receiveString();
    write_log("success = " + error_msg);
    sock.sendString("exit");
    write_log("disconnect");
    sock.disconnect();
    sock = null;
    return error_msg.equals("ok");
  }

/*
  public String receive_strava_token()
  { 
    String token = "";

    write_log("receive strava token");
    sock.sendString("send-file");
    sock.wait("ok");

    sock.sendString("strava.token");
    String msg = sock.receiveString();

    if (msg.equals("ok"))
    { sock.sendString("ok");
      token  = sock.receiveString();
      write_log("token = " + token);
     }
    else
      write_log("error: " + msg);

    sock.sendString("exit");
    write_log("disconnect");
    sock.disconnect();
    sock = null;
    return token;
  }
*/


  public boolean send_file(File file, String title)
  {
    File[] files = new File[1];
    files[0] = file;
    return send_files(files,title);
  }

  public boolean send_files(File[] files, String title) {
      return send_files(files,files.length,title);
  }

  public boolean send_files(File[] files, int n, String title)
  { 
    String cmd = "put-file";

    write_log("send_files");
    sock.sendString(cmd);
    sock.wait("ok");

    sock.sendString(title);
    error_msg = sock.receiveString();
    write_log("send title: " + error_msg);

    if (error_msg.equals("ok"))
    { sock.sendFiles(files,n);
      error_msg = sock.receiveString();
      write_log("send files: " + error_msg);
     }

     sock.sendString("exit");
     write_log("disconnect");
     sock.disconnect();
     sock = null;
     return error_msg.equals("ok");
  }



  public boolean send_crash_report(File file)
  { 
    String cmd = "put-crash";

    write_log("send crash report");
    sock.sendString(cmd);

    sock.wait("ok");
    sock.sendFile(file);
    error_msg = sock.receiveString();
    write_log("success = " + error_msg);
    sock.sendString("exit");
    write_log("disconnect");
    sock.disconnect();
    sock = null;
    return error_msg.equals("ok");
  }


}
