package com.algobase.service;

import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Date;
import java.util.Locale;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;

import android.provider.Settings;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.NotificationChannel;
import android.app.PendingIntent;
import android.app.Service;
import android.app.AppOpsManager;

import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.content.res.Configuration;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.SharedPreferences;

import android.view.View;

import android.widget.RemoteViews;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;

import android.net.Uri;

import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;

import android.os.Build;
import android.os.Environment;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.IBinder;

import android.util.Log;
import android.widget.Toast;

import com.algobase.share.compat.*;

import com.algobase.stracks.sTracksActivity;
import com.algobase.stracks.R;



public class GpsService extends Service {

  static final int NOTIFICATION_ID = 9662;

  static final String CHANNEL_ID = "GPS_Service_ID";
  static final String CHANNEL_NAME = "sTracks GPS Service";

  public static boolean isRunning = false;

  Notification.Builder notificationBuilder;
  NotificationManager notificationManager; 

  LocationManager locationManager;
  LocationListener locationListener;

  Handler handler =  new Handler(Looper.getMainLooper());

  Bitmap icon;
  int icon_res;

  File stracks_folder;
  File gps_folder;
  File current_gps_file;

  GpsPlayer gps_player;

  float client_version;


  private String current_time()
  { Date d = new GregorianCalendar().getTime();
    return new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss").format(d);
  }


  private void log(String msg) 
  { if (msg.equals("")) msg = " ";
    Log.v("GpsService",msg); 
   }


  public void copy_file(File source, File target)
  { try {
        FileInputStream in  = new FileInputStream(source);
        FileOutputStream out = new FileOutputStream(target);
        byte[] buffer = new byte[1024];
        int bytes;
        while((bytes = in.read(buffer)) != -1){
          out.write(buffer, 0, bytes);
        }
       in.close();
       out.close();
     }
     catch(IOException e) { log("copy_file: " + e.toString()); }
  }

        
  public void showToast(final String msg) {
     handler.post( new Runnable() {
        public void run() {
            Toast.makeText(getBaseContext(), msg,Toast.LENGTH_SHORT).show();
        }
     });
  }

  void notify(String title, String text)
  { 
    RemoteViews rviews= new RemoteViews(getPackageName(),
                                        R.layout.notification_gps);

    rviews.setTextColor(R.id.notification_title,0xff000000);
    rviews.setTextColor(R.id.notification_text,0xff000000);

    Intent intent = new Intent(this, GpsService.class);
    intent.putExtra("cmd","stop");
    PendingIntent pendingIntent = PendingIntent.getService(this,12745,
                                          intent,
                                          PendingIntent.FLAG_UPDATE_CURRENT |
                                          PendingIntent.FLAG_IMMUTABLE);

    rviews.setOnClickPendingIntent(R.id.notification_button,
                                                   pendingIntent);

/*
    rviews.setImageViewResource(R.id.notification_image,
                                R.drawable.location48a);

    rviews.setImageViewResource(R.id.notification_icon_right,
                                R.drawable.play_white48);
*/

    rviews.setTextViewText(R.id.notification_title, title);
    rviews.setTextViewText(R.id.notification_text, text);

    if (Build.VERSION.SDK_INT < 24) {
      //notificationBuilder.setContentText(title + "\n" + text);
        notificationBuilder.setContentText(text);
    }
    else
    { //notificationBuilder.setContent(rviews);
      //notificationBuilder.setCustomBigContentView(rviews);
      notificationBuilder.setCustomContentView(rviews);
      notificationBuilder.setStyle(new Notification.DecoratedCustomViewStyle());
     }

    notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
  }



  boolean mockEnabled()
  {
    boolean result = false;

    try
    { AppOpsManager opsManager = 
              (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);

      int checkop = opsManager.checkOp(AppOpsManager.OPSTR_MOCK_LOCATION,
                                       android.os.Process.myUid(),
                                       //BuildConfig.APPLICATION_ID
                                       getPackageName());

      result = (checkop == AppOpsManager.MODE_ALLOWED);
    } catch (Exception e) {};

    return result;
  }


    
    @Override
    public void onCreate() {

      super.onCreate();

      PackageManager pm = getPackageManager();

/*
      try { PackageInfo pi = pm.getPackageInfo(getPackageName(),0);
            client_version = 0.001f * pi.versionCode;
      } catch (Exception e) {}
*/

      client_version = 0.001f*PackageCompat.getVersionCode(this);


/*
      String prefs_file = sTracksActivity.PREFS_NAME;
      config = getSharedPreferences(prefs_file,0);

      String host = config.getString("server_host",null);
      if (host != null) {
          server_host = host;
      }

      lang = config.getString("language","English");

      user_name = config.getString("user","");
*/


      if (sTracksActivity.USE_LEGACY_STORAGE)
      { File sdroot = Environment.getExternalStorageDirectory();
        stracks_folder = new File(sdroot,"sTracks");
       }
      else
        stracks_folder = getFilesDir();

      gps_folder = new File(stracks_folder,"gps");

      current_gps_file = new File(gps_folder,"current_track.gps");

      boolean restart = current_gps_file.exists();

      gps_player = new GpsPlayer(this);

      if (restart)
        log("onCreate (RESTART)");
      else
        log("onCreate");

      log("");

      log("start notification");

       notificationManager = getSystemService(NotificationManager.class);

       if (Build.VERSION.SDK_INT < 26) 
         notificationBuilder = new Notification.Builder(this);
       else 
       { int importance = NotificationManager.IMPORTANCE_LOW;
         NotificationChannel channel = 
                  new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, importance);
         notificationManager.createNotificationChannel(channel);
         notificationBuilder = new Notification.Builder(this,CHANNEL_ID);
       }

       notificationBuilder.setVisibility(Notification.VISIBILITY_SECRET);

       notificationBuilder.setSmallIcon(R.drawable.play_white48);


       notificationBuilder.setOngoing(true);

       notify("GPS Player","");

       startForeground(NOTIFICATION_ID,notificationBuilder.build());


       isRunning = true;


       if (restart) {
         log("Service Restart");
       }

       log("onCreate finished");
       log("");
    }



   @Override
   public int onStartCommand(Intent intent, int flags, int startId) 
   { 
     String cmd = "";
     String fname = null;
     boolean skip = true;
     float speed = 1.0f;
     int start = 0;
     float accuracy = 5.0f;

     if (intent != null) // can it be null ? 
     { if (intent.hasExtra("cmd")) cmd = intent.getStringExtra("cmd");
       if (intent.hasExtra("skip")) skip = intent.getBooleanExtra("skip",true);
       if (intent.hasExtra("file")) fname = intent.getStringExtra("file");
       if (intent.hasExtra("speed")) speed = intent.getFloatExtra("speed",1.0f);
       if (intent.hasExtra("start")) start = intent.getIntExtra("start",0);
       if (intent.hasExtra("accuracy")) 
                          accuracy = intent.getFloatExtra("accuracy",5.0f);
      }

     //showToast("start: cmd = " + cmd);

     log("");
     log("onStartCommand " + current_time());
     log("command = " + cmd);
     log("fname  = " + fname);
     log("speed  = " + speed);
     log("start  = " + start);

     if (cmd.equals("play")) {

        if (!mockEnabled())
        { showToast("Mock Location not enabled");
          stopSelf();
         }
        else
        { File file = new File(fname);

          String title = String.format(Locale.US,"GPS Player  %.1f x",speed);
          String txt = file.getName();

          notify(title,txt);

          gps_player.setMaxBreak(2000);

          gps_player.setSkipBreaks(skip);
          gps_player.setSpeed(speed);
          gps_player.setStart(start);
          gps_player.setAccuracy(accuracy);
          gps_player.start(file);
        }
     }

     if (cmd.equals("stop")) {
        if (gps_player != null) gps_player.stop();
        gps_player = null;
        stopSelf();
      }

      return START_STICKY;
    }



   @Override
   public void onDestroy() 
   {
     log("onDestroy");

     if (gps_player != null) gps_player.stop();

     notificationManager.cancel(NOTIFICATION_ID);
     super.onDestroy();
/*
     log("killProcess");
     android.os.Process.killProcess(android.os.Process.myPid());
*/
     isRunning = false;
   }


   @Override
   public void onConfigurationChanged(Configuration config) 
   { log("onConfigurationChanged: " + config.toString());
     super.onConfigurationChanged(config);
    }

   @Override
   public void onTaskRemoved(Intent intent) 
   { log("onTaskRemoved");
     super.onTaskRemoved(intent);
    }


   @Override
   public void onLowMemory() 
   { log("onLowMemory");
     super.onLowMemory();
    }

/*
   @Override
   public void onTrimMemory(int level) 
   { log("onTrimMemory: level = " + level);
     super.onLowMemory();
    }
*/


  @Override
  public IBinder onBind(Intent intent) { 
     log("onBind");
     return null;
  }

}
