package org.deke.risk.riskahead.helper;

import android.app.NotificationManager;
import android.app.PendingIntent;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.*;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.util.Log;

import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.google.android.gms.maps.model.LatLng;

import org.deke.risk.riskahead.MapsActivity;
import org.deke.risk.riskahead.R;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

public class NotificationService extends Service {

    private final static String TAG = NotificationService.class.getSimpleName();
    private final static String EXTRA_MESSAGE = "org.deke.risk.riskahead.MESSAGE";

    Handler mNotifyHandler  = new Handler();
    NotificationManager mNotificationManager;

    public SessionManager session;
    public HashMap<String, String> user;

    public LocationManager locationManager;

    public NotificationService() {
        super();
    }

    @Override
    public void onCreate(){
        Log.d(TAG,"onCreate NotificationService");

        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        session = new SessionManager(getApplicationContext());
        user = session.getUserDetails();

        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        LocationListener locationListener = new MyLocationListener();
        locationManager.requestLocationUpdates(
                LocationManager.NETWORK_PROVIDER, 5000, 10, locationListener);

        Log.d(TAG, "Service Created. Starting notification task...");
        mNotifyTask.run();
    }

    private class MyLocationListener implements LocationListener {

        @Override
        public void onLocationChanged(Location loc) {
            String longitude = "Longitude: " + loc.getLongitude();
            Log.v(TAG, longitude);
            String latitude = "Latitude: " + loc.getLatitude();
            Log.v(TAG, latitude);

            if(session.isGPSForNotificationsEnabled() && loc.getLongitude() != 0.0 && loc.getLatitude() != 0.0) {
                Log.d(TAG, "Save GPS as new location...");
                if(session.getLocation() == null || session.getLocation().latitude == 0.0 || session.getLocation().longitude == 0.0){
                    session.setLocation(Double.doubleToRawLongBits(loc.getLatitude()), Double.doubleToRawLongBits(loc.getLongitude()));
                    mNotifyHandler.removeCallbacksAndMessages(null);
                    mNotifyTask.run();
                }else{
                    session.setLocation(Double.doubleToRawLongBits(loc.getLatitude()), Double.doubleToRawLongBits(loc.getLongitude()));
                }

                session.setNotificationServiceReady(true);

            }else{
                Log.d(TAG,"Don't Save GPS as new location because GPS for notifications is disabled...: "+session.isGPSForNotificationsEnabled());
            }
        }

        @Override
        public void onProviderDisabled(String provider) {}

        @Override
        public void onProviderEnabled(String provider) {}

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {}
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    Runnable mNotifyTask = new Runnable() {
        @Override
        public void run() {
            android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);

            LatLng myPosition = session.getLocation();
            int radius = session.getNotificationRadius();
            int pollFrequency = session.getNotificationPollFreq() * 1000 * 60;
            boolean notifyEnabled = session.getNotificationEnabled();

            Log.d(this.toString(), "Run Notification Task. Notifications enabled = " + notifyEnabled);

            if(notifyEnabled && session.isLoggedIn()){
                if ((myPosition != null) && (myPosition.latitude != 0.0) && (myPosition.longitude != 0.0)) {
                    session.setNotificationServiceReady(true);
                    String lastNotificationTime;

                    if (session.getLastNotification().equals("")) {
                        lastNotificationTime = user.get(SessionManager.KEY_LASTLOGIN_AT);
                    } else {
                        lastNotificationTime = session.getLastNotification();
                    }

                    Log.d(this.toString(), "Lookup location with position: " + myPosition + " Radius: "+ radius +" PollFrequency: "+ pollFrequency +" lastNotifyTime: " + lastNotificationTime);

                    StringRequest strReq = getStringRequestIncidentsFromAreaAndTime(myPosition.latitude, myPosition.longitude, radius, lastNotificationTime);
                    String tag_string_req = "req_incidents";
                    AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
                }else{
                    Log.d(TAG,"No position found. No notification send.");
                    session.setNotificationServiceReady(false);
                }
            }


            mNotifyHandler.postDelayed(mNotifyTask, pollFrequency);
        }
    };

    private StringRequest getStringRequestIncidentsFromAreaAndTime(final Double latitude, final Double longitude, final int radius, final String time) {
        return new StringRequest(Request.Method.POST, AppConfig.URL_DEFAULT, new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                Log.d(TAG, "Incident notifications: " + response);

                try {
                    JSONObject jObj = new JSONObject(response);
                    boolean error = jObj.getBoolean("error");

                    if (!error) {
                        JSONArray notification = jObj.getJSONArray("msg");

                        sentNotification(notification);
                    } else {
                        String errorMsg = jObj.getString("error_msg");
                        Log.e(TAG, "Error getting incident notification (server returned error): " + errorMsg);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "Error getting incident notification: " + error.getMessage());
            }
        }) {

            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<>();
                params.put("tag", "getincidentsinareaandtime");
                params.put("uid", user.get(SessionManager.KEY_UID));
                params.put("token", user.get(SessionManager.TOKEN));
                params.put("latitude", Double.toString(latitude));
                params.put("longitude", Double.toString(longitude));
                params.put("radius", Integer.toString(radius));
                params.put("time", "'"+time+"'");
                return params;
            }
        };
    }

    private void sentNotification(JSONArray notification) {
        String title;
        String context;

        if(notification.length() == 1){
            title = getString(R.string.txt_notification_title);
            context = notification.length() + " " + getString(R.string.txt_notification_context);
        }else{
            title = getString(R.string.txt_notification_title_multi);
            context = notification.length() + " " + getString(R.string.txt_notification_context_multi);
        }
        NotificationCompat.Builder mBuilder =
                new NotificationCompat.Builder(getApplicationContext())
                        .setSmallIcon(R.drawable.logo_riskahead)
                        .setAutoCancel(true)
                        .setContentTitle(title)
                        .setContentText(context);


        Intent resultIntent = new Intent(this, MapsActivity.class);

        try {
            resultIntent.putExtra(EXTRA_MESSAGE, notification.getJSONObject(notification.length()-1).getDouble("latitude")+":"+notification.getJSONObject(notification.length()-1).getDouble("longitude"));
        } catch (JSONException e) {
            e.printStackTrace();
        }

        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
        stackBuilder.addParentStack(MapsActivity.class);

        stackBuilder.addNextIntent(resultIntent);
        PendingIntent resultPendingIntent =
                stackBuilder.getPendingIntent(
                        0,
                        PendingIntent.FLAG_UPDATE_CURRENT
                );
        mBuilder.setContentIntent(resultPendingIntent);

        int mId = 1;
        mNotificationManager.notify(mId, mBuilder.build());

        session.setLastNotification(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime()));

    }

    @Override
    public void onDestroy(){
        super.onDestroy();
        Log.d(TAG, "Destroy NotificationService");
    }


}
