package com.selfservit.util;

import android.Manifest;
import android.annotation.TargetApi;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.app.Notification;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.location.Location;
import android.media.RingtoneManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.os.SystemClock;

import java.text.DateFormat;
import java.util.Arrays;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.NotificationCompat;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

import org.json.JSONArray;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;

import java.io.BufferedReader;
import java.io.File;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

public class mInterfaceService extends Service implements com.google.android.gms.location.LocationListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
    public Timer setQueueInterval,
            setQueueToServerInterval,
            setTimerIntervel,
            setProcessInterval,
            setChecksumTimerInterval;
    GoogleApiClient mGoogleApiClient;
    private static final int ALL_PERMISSIONS_RESULT =0;
    private static final long INTERVAL = 3000 * 10;
    private static final long FASTEST_INTERVAL = 3000 * 10;
    LocationRequest mLocationRequest;
    Location mCurrentLocation;
    String mLastUpdateTime;

    @ Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
    @ Override
    @TargetApi(Build.VERSION_CODES.M)
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String NOTIFICATION_CHANNEL_ID = "com.selfservice.mservice";
            String channelName = "MService Background Service";
            NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE);
            chan.setLightColor(Color.BLUE);
            chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
            NotificationManager manager = (NotificationManager) getSystemService(this.NOTIFICATION_SERVICE);
            assert manager != null;
            manager.createNotificationChannel(chan);

            Uri uri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
            NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
            Notification notification = notificationBuilder.setOngoing(true)
                    .setContentTitle("App is running in background")
                    .setPriority(NotificationManager.IMPORTANCE_MIN)
                    .setCategory(Notification.CATEGORY_SERVICE)
                    .setChannelId(NOTIFICATION_CHANNEL_ID)
                    .setVibrate(new long[] { 1000, 1000, 1000, 1000, 1000 })
                    .setSound(uri)
                    .setVisibility(NotificationCompat.VISIBILITY_PRIVATE)
                    .build();
            startForeground(2, notification);
        } else {
            Notification notification = new NotificationCompat.Builder(this).build();
            startForeground(1, notification);
        }
        TimerTask setQueueIntervalObj,
                setQueueToServerObj,
                setTimerIntervelObj,
                setProcessIntervalObj,
                setChecksumTimerIntervalObj;
        Intent serviceIntent = new Intent(getApplicationContext(), mInterfaceReceiver.class);
        serviceIntent.setAction("com.example.checkservice");
        final PendingIntent pIntent = PendingIntent.getBroadcast(getApplicationContext(), 0,
                serviceIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        long firstMillis = System.currentTimeMillis();
        AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
        alarm.setRepeating(AlarmManager.RTC_WAKEUP, firstMillis,
                300000, pIntent);

        // ****Queue Manager New Process Interval Timer ***** //
        setQueueInterval = new Timer();
        setQueueIntervalObj = new TimerTask() {
            public void run() {
                if (isConnected()) {
                    new DespatchQueueNew().execute();
                }
            }
        };
        setQueueInterval.schedule(setQueueIntervalObj, 2000, 2000);

        setQueueToServerInterval = new Timer();
        setQueueIntervalObj = new TimerTask() {
            public void run() {
                if (isConnected()) {
                    new DespatchQueueMoveToServer().execute();
                }
            }
        };
        setQueueToServerInterval.schedule(setQueueIntervalObj, 2000, 2000);

        // **** TimeReader Interval Timer ***** //
        setTimerIntervel = new Timer();
        setTimerIntervelObj = new TimerTask() {
            public void run() {
                try {
                    timeReader();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        setTimerIntervel.schedule(setTimerIntervelObj, 60000, 60000);

        // *** CheckSum value Indicator Timer *** //
        setChecksumTimerInterval = new Timer();
        setChecksumTimerIntervalObj = new TimerTask() {
            public void run() {
                try {
                    if (isConnected()) {
                        new CheckSumIndicatorResult().execute();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        setChecksumTimerInterval.schedule(setChecksumTimerIntervalObj, 180000, 180000);

        /* AUTHENTICATION PROCESS */
        setProcessInterval = new Timer();
        setProcessIntervalObj = new TimerTask() {
            public void run() {
                if (isConnected()) {
                    new AuthenticationRefresh().execute();
                }
            }
        };
        setProcessInterval.schedule(setProcessIntervalObj, 600000, 600000);

        if (!isGooglePlayServicesAvailable()) {
            System.out.println("Play services not available..");
        }
        createLocationRequest();
        this.mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        mGoogleApiClient.connect();
        return START_STICKY;
    }

    private boolean isGooglePlayServicesAvailable() {
        int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (ConnectionResult.SUCCESS == resultCode) {
            return true;
        } else {
            return false;
        }
    }
    public void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(INTERVAL);
        mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }
    protected void startLocationUpdates() {
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
			if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

			}
		}
        PendingResult<Status> pendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }
    @Override
    public void onLocationChanged(Location location) {
        mCurrentLocation = location;
        mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
        String lat = String.valueOf(mCurrentLocation.getLatitude());
        String lng = String.valueOf(mCurrentLocation.getLongitude());
        new UpdateLocation(lat, lng).execute("");
        if (isConnected()) {
            new SendLocation().execute();
        }
        String string = ("Latitude : " + lat + "Longitude : " + lng + "\n");
        System.out.println(string);
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        startLocationUpdates();
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

    }

    private class DespatchQueueNew extends AsyncTask < String,
            Void,
            String > {
        @ Override
        protected String doInBackground(String...params) {
            File baseDirectory = Environment.getExternalStorageDirectory();
            File processDir = new File(baseDirectory.getAbsolutePath() + "/" + mInterfaceUtil.packageName + "/database/queue/");
            String currentLine,
                    sendData,
                    fileType,
                    sendFileName,
                    requestFilepath,
                    sendFileBasePath,
                    method,
                    keyValue,
                    subKeyValue,
                    requesturl = "",
                    receiveData = "";
            StringBuilder serverResponseObj,
                    backupFileData;
            BufferedReader readerObj;
            BufferedWriter writerObj;
            File backUpFilePath;
            FileInputStream fileInputStream;
            int bytesRead,
                    bytesAvailable,
                    bufferSize;
            byte[]buffer;
            int maxBufferSize = 1 * 1024 * 1024;
            DataOutputStream dos;
            String lineEnd = "\r\n";
            String twoHyphens = "--";
            String boundary = "*****";
            JSONObject queueObject,
                    backupDataObj;
            URL requestPath;
            HttpURLConnection urlConObj;
            OutputStreamWriter oStreamObj;
            StringBuilder queueObj = new StringBuilder();
            try {
                if (processDir.exists()) {
                    File[]fileList = processDir.listFiles();
                    if (fileList != null && fileList.length >= 1) {
                        Arrays.sort(fileList);
                        File fileIndex = fileList[0];
                        readerObj = new BufferedReader(new FileReader(fileIndex));
                        while ((currentLine = readerObj.readLine()) != null) {
                            queueObj.append(currentLine);
                        }
                        readerObj.close();
                        if (isConnected()) {
                            /* FROM REQUEST OBJECT */
                            queueObject = new JSONObject(queueObj.toString());
                            requesturl = queueObject.optString("url").toString();
                            sendData = queueObject.optString("input").toString();
                            fileType = queueObject.optString("type").toString();
                            sendFileBasePath = queueObject.optString("filepath").toString();
                            sendFileName = queueObject.optString("filename").toString();
                            method = queueObject.optString("method").toString();
                            keyValue = queueObject.optString("key").toString();
                            subKeyValue = queueObject.optString("subkey").toString();

                            /* UPLOAD FILE TO SERVER */
                            if (method.equals("read")) {
                                backUpFilePath = new File(baseDirectory.getAbsolutePath() + "/" + mInterfaceUtil.packageName + "/" + (new JSONObject(queueObject.optString("input")).optJSONObject("context").optString("client_id").toString()) + "/" + (new JSONObject(queueObject.optString("input")).optJSONObject("context").optString("country_code").toString()) + "/database/" + "bckp_" + keyValue + ".txt");
                                requestPath = new URL(requesturl);
                                urlConObj = (HttpURLConnection)requestPath.openConnection();
                                urlConObj.setDoOutput(true);
                                urlConObj.setRequestMethod("POST");
                                urlConObj.setRequestProperty("CONTENT-TYPE", "application/json");
                                urlConObj.connect();
                                oStreamObj = new OutputStreamWriter(urlConObj.getOutputStream());
                                oStreamObj.write(sendData);
                                oStreamObj.flush();
                                oStreamObj.close();

                                /* GET RESPONSE FROM SERVER*/
                                serverResponseObj = new StringBuilder();
                                readerObj = new BufferedReader(new InputStreamReader(urlConObj.getInputStream()));
                                while ((currentLine = readerObj.readLine()) != null) {
                                    serverResponseObj.append(currentLine);
                                }
                                readerObj.close();
                                urlConObj.disconnect();
                                backupFileData = new StringBuilder();
                                try {
                                    if (backUpFilePath.exists()) {
                                        readerObj = new BufferedReader(new FileReader(backUpFilePath));
                                        while ((currentLine = readerObj.readLine()) != null) {
                                            backupFileData.append(currentLine + "\n");
                                        }
                                        readerObj.close();
                                        backupDataObj = new JSONObject(backupFileData.toString());
                                    } else {
                                        backUpFilePath.createNewFile();
                                        backupDataObj = new JSONObject();
                                    }
                                    backupDataObj.put(subKeyValue, new JSONArray(serverResponseObj.toString()));
                                    writerObj = new BufferedWriter(new FileWriter(backUpFilePath));
                                    writerObj.write(backupDataObj.toString());
                                    writerObj.flush();
                                    writerObj.close();
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            } else {
                                if (fileType.equals("file")) {
                                    requestFilepath = baseDirectory + "/" + sendFileBasePath + "/" + sendFileName;
                                    if (new File(requestFilepath).exists()) {
                                        fileInputStream = new FileInputStream(new File(requestFilepath));
                                        requestPath = new URL((requesturl + "&filename=" + sendFileName).replaceAll(" ", "%20"));
                                        urlConObj = (HttpURLConnection)requestPath.openConnection();
                                        urlConObj.setDoInput(true); // Allow Inputs
                                        urlConObj.setDoOutput(true); // Allow Outputs
                                        urlConObj.setUseCaches(false); // Don't use a Cached Copy
                                        urlConObj.setRequestMethod("POST");
                                        urlConObj.setRequestProperty("Connection", "Keep-Alive");
                                        urlConObj.setRequestProperty("ENCTYPE", "multipart/form-data");
                                        urlConObj.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
                                        urlConObj.setRequestProperty("uploaded_file", sendFileName);

                                        dos = new DataOutputStream(urlConObj.getOutputStream());
                                        dos.writeBytes(twoHyphens + boundary + lineEnd);
                                        dos.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\";filename=\""
                                                + sendFileName + "\"" + lineEnd);
                                        dos.writeBytes(lineEnd);
                                        // create a buffer of  maximum size
                                        bytesAvailable = fileInputStream.available();

                                        bufferSize = Math.min(bytesAvailable, maxBufferSize);
                                        buffer = new byte[bufferSize];

                                        // read file and write it into form...
                                        bytesRead = fileInputStream.read(buffer, 0, bufferSize);
                                        while (bytesRead > 0) {
                                            dos.write(buffer, 0, bufferSize);
                                            bytesAvailable = fileInputStream.available();
                                            bufferSize = Math.min(bytesAvailable, maxBufferSize);
                                            bytesRead = fileInputStream.read(buffer, 0, bufferSize);

                                        }
                                        // send multipart form data necesssary after file data...
                                        dos.writeBytes(lineEnd);
                                        dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
                                        urlConObj.getResponseCode();
                                        //close the streams //
                                        fileInputStream.close();
                                        dos.flush();
                                        dos.close();
                                        serverResponseObj = new StringBuilder();
                                        readerObj = new BufferedReader(new InputStreamReader(urlConObj.getInputStream()));
                                        while ((currentLine = readerObj.readLine()) != null) {
                                            serverResponseObj.append(currentLine + "\n");
                                        }
                                        readerObj.close();
                                        receiveData += "Time:" + new SimpleDateFormat("HH:mm:ss",new mInterfaceUtil().locale).format(new Date()) + "\n";
                                        receiveData += "url:" + requestPath + "\n";
                                        receiveData += "------------------\n";
                                        urlConObj.disconnect();
                                    }
                                } else {
                                    /* SEND JSON DATA TO SERVER*/
                                    requestPath = new URL(requesturl);
                                    urlConObj = (HttpURLConnection)requestPath.openConnection();
                                    urlConObj.setDoOutput(true);
                                    urlConObj.setRequestMethod("POST");
                                    urlConObj.setRequestProperty("CONTENT-TYPE", "application/json");
                                    urlConObj.connect();
                                    oStreamObj = new OutputStreamWriter(urlConObj.getOutputStream());
                                    oStreamObj.write(sendData);
                                    oStreamObj.flush();
                                    oStreamObj.close();

                                    /* GET RESPONSE FROM SERVER*/
                                    serverResponseObj = new StringBuilder();
                                    readerObj = new BufferedReader(new InputStreamReader(urlConObj.getInputStream()));
                                    while ((currentLine = readerObj.readLine()) != null) {
                                        serverResponseObj.append(currentLine + "\n");
                                    }
                                    readerObj.close();
                                    receiveData += "Time:" + new SimpleDateFormat("HH:mm:ss",new mInterfaceUtil().locale).format(new Date()) + "\n";
                                    receiveData += "url:" + requesturl + "\n";
                                    receiveData += "data:" + sendData + "\n";
                                    receiveData += "response:" + serverResponseObj.toString() + "\n";
                                    receiveData += "------------------\n";
                                    urlConObj.disconnect();
                                }
                            }
                            new mInterfaceUtil().logData(mInterfaceUtil.packageName + "/database/process/" + new SimpleDateFormat("yyyyMMdd",new mInterfaceUtil().locale).format(new Date()) + ".txt", receiveData);
                            fileIndex.delete ();
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    private class DespatchQueueMoveToServer extends AsyncTask < String,
            Void,
            String > {
        @ Override
        protected String doInBackground(String...params) {
            String statusIndication = "false";
            try {
                String clientID, countryCode, userID, clientUrl;
                BufferedReader myAccountsFileReader;
                StringBuilder myAccountsFileBuilder;
                JSONArray accountsList;
                JSONObject currentAccount;
                String currentLine;
                if (new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/" + "my_accounts.txt").exists()) {
                    myAccountsFileReader = new BufferedReader(new FileReader(new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/" + "my_accounts.txt")));
                    myAccountsFileBuilder = new StringBuilder();
                    while ((currentLine = myAccountsFileReader.readLine()) != null) {
                        myAccountsFileBuilder.append(currentLine);
                    }
                    myAccountsFileReader.close();
                    accountsList = new JSONArray(myAccountsFileBuilder.toString());
                    if (isConnected()) {
                        for (int index = 0; index < accountsList.length(); index++) {
                            currentAccount = accountsList.optJSONObject(index);
                            clientID = currentAccount.optString("client_id").toString();
                            countryCode = currentAccount.optString("country_code").toString();
                            userID = currentAccount.optString("user_id").toString();
                            clientUrl = currentAccount.optString("client_url").toString();
                            File baseDirectory = Environment.getExternalStorageDirectory();
                            File databaseDir = new File(baseDirectory.getAbsolutePath() + "/" + mInterfaceUtil.packageName + "/" + clientID + "/" + countryCode + "/database");
                            File processFileDir = new File(mInterfaceUtil.packageName + "/" + clientID + "/" + countryCode + "/database/process/");
                            if(databaseDir.exists()) {
                                String attachmentsPath = baseDirectory.getAbsolutePath() + "/" + mInterfaceUtil.packageName + "/" + clientID + "/" + countryCode + "/database/attachments";
                                String queuesPath = baseDirectory.getAbsolutePath() + "/" + mInterfaceUtil.packageName + "/" + clientID + "/" + countryCode + "/database/queue";
                                if(new File(attachmentsPath).exists()) {
                                    File[] attachmentsFiles = new File(attachmentsPath).listFiles();
                                    if(attachmentsFiles != null) {
                                        for (int attachIndex = 0; attachIndex < attachmentsFiles.length; attachIndex++) {
                                            if(attachmentsFiles[attachIndex].length() == 0) {
                                                break;
                                            }
                                            String[] fileName = attachmentsFiles[attachIndex].toString().split("/");
                                            String attachURL = clientUrl + "/common/components/QueueManager/QueueUpload.aspx?file_path=attachments&client_id=" + clientID + "&country_code=" + countryCode + "&user_id=" + userID + "&file_name=" + fileName[fileName.length-1].toString();
                                            statusIndication = new mInterfaceUtil().sendFilesToServer(attachmentsFiles[attachIndex].toString(), fileName[fileName.length-1].toString(), attachURL);
                                            if(statusIndication.equals("true")) {
                                                break;
                                            }
                                        }
                                    }
                                }
                                if(statusIndication.equals("false")) {
                                    if(new File(queuesPath).exists()) {
                                        File[] queueFiles = new File(queuesPath).listFiles();
                                        if(queueFiles != null) {
                                            for (int queueIndex = 0; queueIndex < queueFiles.length; queueIndex++) {
                                                if(queueFiles[queueIndex].length() == 0) {
                                                    break;
                                                }
                                                String[] fileName = queueFiles[queueIndex].toString().split("/");
                                                String queueURL = clientUrl + "/common/components/QueueManager/QueueUpload.aspx?file_path=queue&client_id=" + clientID + "&country_code=" + countryCode + "&user_id=" + userID + "&file_name=" + fileName[fileName.length-1].toString();
                                                new mInterfaceUtil().sendFilesToServer(queueFiles[queueIndex].toString(), fileName[fileName.length-1].toString(), queueURL);
                                            }
                                        }
                                    }
                                }
                            } else {
                                System.out.println("No database directory");
                            }
                        }
                    } else {
                        System.out.println("No internet connection..");
                    }
                } else {
                    System.out.println("No my accounts file");
                }
            } catch (Exception e) {
                System.out.println("out exception : " + e.getMessage());
            }
            return null;
        }
        @Override
        protected void onPostExecute(String result) {
            //Here you are done with the task
            System.out.println("Finished...");
        }		    
    }

    private void timeReader()throws Exception {
        String serverTimeObj;
        SimpleDateFormat simpleDateFormat;
        StringBuilder timeObj;
        String currentLine;
        BufferedReader readerObj;
        JSONObject serverDateObj;
        timeObj = new StringBuilder();
        BufferedWriter writerObj;
        File baseDirectory = Environment.getExternalStorageDirectory();
        readerObj = new BufferedReader(new FileReader(new File(baseDirectory, "/" + mInterfaceUtil.packageName + "/" + "time_profile.txt")));
        while ((currentLine = readerObj.readLine()) != null) {
            timeObj.append(currentLine);
        }
        readerObj.close();
        serverDateObj = new JSONObject(timeObj.toString());
        serverTimeObj = serverDateObj.optString("serverDate").toString();

        // ******SERVER TIME ******//
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy,MM,dd,HH,mm,ss",new mInterfaceUtil().locale);
        //String currentDateandTime = sdf.format(new Date());
        simpleDateFormat = new SimpleDateFormat("yyyy,MM,dd,HH,mm,ss",new mInterfaceUtil().locale);
        Date date = simpleDateFormat.parse(serverTimeObj);
        long a = date.getTime() + 60000;
        date.setTime(a);
        serverTimeObj = simpleDateFormat.format(date);
        serverDateObj.put("serverDate", serverTimeObj);
        writerObj = new BufferedWriter(new FileWriter(new File(baseDirectory, "/" + mInterfaceUtil.packageName + "/" + "time_profile.txt")));
        writerObj.write(serverDateObj.toString());
        writerObj.flush();
        writerObj.close();
    }

    private class CheckSumIndicatorResult extends AsyncTask < String,
            Void,
            String > {
        @ Override
        protected String doInBackground(String...strings) {
            String currentLine, sessionID, localeID, clientID, countryCode, userID, cvsUrl, clientUrl, deviceID, employeeID;
            BufferedReader myAccountsFileReader, responseReaderObj;
            StringBuilder myAccountsFileBuilder;
            JSONArray accountsList;
            JSONObject currentAccount, responseDataObj;
            File baseDirectory,
                    checksumFile,
                    userProfileFile;
            BufferedReader checksumFileReader,
                    userProfileFileReader,
                    responseReader;
            String checksumFileData,
                    checksumValue,
                    refreshIndValue,
                    userProfileFileData,
                    serverResponseData;
            JSONObject checksumObj, serverResponseObj,
                    userProfileObj;

            JSONArray serverResponseArray;

            URL requestPath;

            HttpURLConnection urlConObj;

            OutputStreamWriter oStreamObj;

            FileWriter writerObj;

            try {
                baseDirectory = Environment.getExternalStorageDirectory();
                checksumFileData = "";
                checksumValue = "";
                refreshIndValue = "";
                userProfileFileData = "";
                serverResponseData = "";

                if (new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/" + "my_accounts.txt").exists()) {
                    myAccountsFileReader = new BufferedReader(new FileReader(new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/" + "my_accounts.txt")));
                    myAccountsFileBuilder = new StringBuilder();
                    while ((currentLine = myAccountsFileReader.readLine()) != null) {
                        myAccountsFileBuilder.append(currentLine);
                    }
                    myAccountsFileReader.close();

                    accountsList = new JSONArray(myAccountsFileBuilder.toString());
                    for (int index = 0; index < accountsList.length(); index++) {
                        currentAccount = accountsList.optJSONObject(index);

                        sessionID = currentAccount.optString("session_id").toString();
                        localeID = currentAccount.optString("locale_id").toString();
                        clientID = currentAccount.optString("client_id").toString();
                        countryCode = currentAccount.optString("country_code").toString();
                        userID = currentAccount.optString("user_id").toString();
                        employeeID = currentAccount.optString("employee_id").toString();
                        cvsUrl = currentAccount.optString("cvs_url").toString();
                        clientUrl = currentAccount.optString("client_url").toString();
                        deviceID = currentAccount.optString("device_id").toString();

                        /* READ THE CHECKSUM VALUE AND GET CHECKSUM AND REFRESH INDICATOR VALUE*/
                        checksumFile = new File(baseDirectory, "/" + mInterfaceUtil.packageName + "/" + clientID + "/" + countryCode + "/" + "database/checksum_value.txt");
                        if (checksumFile.exists()) {
                            checksumFileReader = new BufferedReader(new FileReader(checksumFile));
                            while ((currentLine = checksumFileReader.readLine()) != null) {
                                checksumFileData += currentLine;
                            }
                            checksumFileReader.close();
                            checksumObj = new JSONObject(checksumFileData);
                            checksumValue = checksumObj.optString("checksum_value").toString();
                            refreshIndValue = checksumObj.optString("refresh_ind").toString();
                        }

                        if (refreshIndValue.matches("") || refreshIndValue.matches("false")) {
                            /* SEND VALIDATE CHECKSUM REQUEST TO SERVER */
                            requestPath = new URL(clientUrl + "/JSONServiceEndpoint.aspx?appName=common_modules&serviceName=retrieve_listof_values_for_searchcondition&path=context/outputparam");
                            urlConObj = (HttpURLConnection)requestPath.openConnection();
                            urlConObj.setDoOutput(true);
                            urlConObj.setRequestMethod("POST");
                            urlConObj.setRequestProperty("CONTENT-TYPE", "application/json");
                            urlConObj.connect();

                            oStreamObj = new OutputStreamWriter(urlConObj.getOutputStream());
                            oStreamObj.write("{\"context\":{\"sessionId\":" + "\"" + sessionID + "\"" + ",\"userId\":" + "\"" + userID + "\"" + ",\"client_id\":" + "\"" + clientID + "\"" + ",\"locale_id\":" + "\"" + localeID + "\"" + ",\"country_code\":" + "\"" + countryCode + "\"" + ",\"inputparam\":{\"p_inputparam_xml\":\"<inputparam><lov_code_type>VALIDATE_CHECKSUM</lov_code_type><search_field_1>" + checksumValue + "</search_field_1><search_field_2>" + employeeID + "</search_field_2><search_field_3>MOBILE</search_field_3></inputparam>\"}}}");
                            oStreamObj.flush();
                            oStreamObj.close();

                            /* READ THE SERVER RESPONSE AND WRITE TO THE FILE */
                            responseReader = new BufferedReader(new InputStreamReader(urlConObj.getInputStream()));
                            while ((currentLine = responseReader.readLine()) != null) {
                                serverResponseData += currentLine;
                            }
                            responseReader.close();
                            urlConObj.disconnect();

                            serverResponseArray = new JSONArray(serverResponseData);
                            serverResponseObj = serverResponseArray.optJSONObject(0);
                            writerObj = new FileWriter(checksumFile);
                            writerObj.write(serverResponseObj.toString());
                            writerObj.flush();
                            writerObj.close();
                            String date,
                                    hour,
                                    minute;
                            date = serverResponseObj.optString("serverDate").toString();
                            hour = serverResponseObj.optString("serverHour").toString();
                            minute = serverResponseObj.optString("serverMinute").toString();
                            new mInterfaceUtil().refreshTimeProfile(date, hour, minute);

                        }
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return null;
        }
    }

    public void getLocationUpdate() {

    }

    private class SendLocation extends AsyncTask < String,
            Void,
            String > {
        @ Override
        protected String doInBackground(String...urls) {
            String currentLine, sessionID, localeID, clientID, countryCode, userID, cvsUrl, clientUrl, deviceID, employeeID;
            BufferedReader myAccountsFileReader, responseReaderObj;
            StringBuilder myAccountsFileBuilder;
            JSONArray accountsList;
            JSONObject currentAccount, responseDataObj;
            StringBuilder locationData,
                    userData;
            BufferedReader readerObj;
            BufferedWriter writerObj;
            String serverData,
                    requesturl;
            DocumentBuilderFactory dbfObj;
            DocumentBuilder dbObj;
            Document docObj;
            OutputStreamWriter oStreamObj;


            JSONObject userObj;
            HttpURLConnection urlConObj;
            URL requestPath;

            try {
                File baseDirectory = Environment.getExternalStorageDirectory();
                if (new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/" + "my_accounts.txt").exists()) {
                    myAccountsFileReader = new BufferedReader(new FileReader(new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/" + "my_accounts.txt")));
                    myAccountsFileBuilder = new StringBuilder();
                    while ((currentLine = myAccountsFileReader.readLine()) != null) {
                        myAccountsFileBuilder.append(currentLine);
                    }
                    myAccountsFileReader.close();

                    accountsList = new JSONArray(myAccountsFileBuilder.toString());

                    /* GETTING THE LOCATION POINTS TO BE SENT TO THE SERVER */
                    locationData = new StringBuilder();
                    readerObj = new BufferedReader(new FileReader(new File(baseDirectory, "/" + mInterfaceUtil.packageName + "/MyLocation.txt")));
                    while ((currentLine = readerObj.readLine()) != null) {
                        locationData.append(currentLine + "\n");
                        //lastKnownLocation = currentLine + "\n";
                    }
                    readerObj.close();
                    serverData = locationData.toString();

                    /* CLEARING THE LOCATION POINTS */
                    if (serverData != "") {
                        writerObj = new BufferedWriter(new FileWriter(new File(baseDirectory, "/" + mInterfaceUtil.packageName + "/MyLocation.txt")));
                        writerObj.write("");
                        writerObj.flush();
                        writerObj.close();
                    }


                    for (int index = 0; index < accountsList.length(); index++) {
                        currentAccount = accountsList.optJSONObject(index);

                        sessionID = currentAccount.optString("session_id").toString();
                        localeID = currentAccount.optString("locale_id").toString();
                        clientID = currentAccount.optString("client_id").toString();
                        countryCode = currentAccount.optString("country_code").toString();
                        userID = currentAccount.optString("user_id").toString();
                        employeeID = currentAccount.optString("employee_id").toString();
                        cvsUrl = currentAccount.optString("cvs_url").toString();
                        clientUrl = currentAccount.optString("client_url").toString();
                        deviceID = currentAccount.optString("device_id").toString();

                        requesturl = clientUrl + "/common/components/GeoLocation/update_device_location_offline.aspx";

                        /* SEND LOCATION  */
                        requestPath = new URL(requesturl);
                        urlConObj = (HttpURLConnection)requestPath.openConnection();
                        urlConObj.setDoOutput(true);
                        urlConObj.setRequestMethod("POST");
                        urlConObj.setRequestProperty("CONTENT-TYPE", "text/xml");
                        urlConObj.connect();
                        oStreamObj = new OutputStreamWriter(urlConObj.getOutputStream());
                        oStreamObj.write("<location_xml><client_id>" + clientID + "</client_id><country_code>" + countryCode + "</country_code><device_id>" + deviceID + "</device_id><location>" + serverData + "</location></location_xml>");
                        oStreamObj.flush();
                        oStreamObj.close();
                        urlConObj.getResponseCode();
                        urlConObj.disconnect();
                    }
                }
            } catch (Exception ex){
                ex.printStackTrace();
            }
            return null;
        }
    }
    private class UpdateLocation extends AsyncTask < String,
            Void,
            String > {
        private String objLat,
                objLon;

        public UpdateLocation(String lat, String lon) {
            this.objLat = lat;
            this.objLon = lon;
        }

        @ Override
        protected String doInBackground(String...urls) {
            File appDirectory,
                    baseDirectory = Environment.getExternalStorageDirectory();
            FileWriter fileWriterObj;
            appDirectory = new File(baseDirectory.getAbsolutePath() + "/" + mInterfaceUtil.packageName);
            if (appDirectory.exists()) {
                try {
                    fileWriterObj = new FileWriter(new File(baseDirectory, mInterfaceUtil.packageName + "/MyLocation.txt"), true);
                    fileWriterObj.write(this.objLat + "," + this.objLon + "," + new SimpleDateFormat("yyyyMMddHHmmss",new mInterfaceUtil().locale).format(new Date()) + "\n");
                    fileWriterObj.flush();
                    fileWriterObj.close();

                    fileWriterObj = new FileWriter(new File(baseDirectory, mInterfaceUtil.packageName + "/LastKnownLocation.txt"), false);
                    fileWriterObj.write(this.objLat + "," + this.objLon + "," + new SimpleDateFormat("yyyyMMddHHmmss",new mInterfaceUtil().locale).format(new Date()));
                    fileWriterObj.flush();
                    fileWriterObj.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return null;
        }
    }


    /* AUTHENICATION PROCESS */
    private class AuthenticationRefresh extends AsyncTask < String,
            Void,
            String > {

        @ Override
        protected String doInBackground(String...strings) {
            String currentLine, sessionID, localeID, clientID, countryCode, userID, cvsUrl, clientUrl, deviceID;
            BufferedReader myAccountsFileReader, responseReaderObj;
            StringBuilder myAccountsFileBuilder, serverResponseObj;
            JSONArray accountsList;
            JSONObject currentAccount, responseDataObj;
            URL requestAuthenticationPath,
                    requestValidateDevicePath;
            HttpURLConnection urlConObj;
            OutputStreamWriter oStreamObj;
            BufferedWriter writerObj;

            try {
                if (new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/" + "my_accounts.txt").exists()) {
                    myAccountsFileReader = new BufferedReader(new FileReader(new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/" + "my_accounts.txt")));
                    myAccountsFileBuilder = new StringBuilder();
                    while ((currentLine = myAccountsFileReader.readLine()) != null) {
                        myAccountsFileBuilder.append(currentLine);
                    }
                    myAccountsFileReader.close();

                    accountsList = new JSONArray(myAccountsFileBuilder.toString());
                    for (int index = 0; index < accountsList.length(); index++) {
                        currentAccount = accountsList.optJSONObject(index);

                        sessionID = currentAccount.optString("session_id").toString();
                        localeID = currentAccount.optString("locale_id").toString();
                        clientID = currentAccount.optString("client_id").toString();
                        countryCode = currentAccount.optString("country_code").toString();
                        userID = currentAccount.optString("user_id").toString();
                        cvsUrl = currentAccount.optString("cvs_url").toString();
                        clientUrl = currentAccount.optString("client_url").toString();
                        deviceID = currentAccount.optString("device_id").toString();

                        if (new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/" + clientID + "/" + countryCode + "/" + "auth_indication.txt").exists()) {
                            BufferedReader authFileReader = new BufferedReader(new FileReader(new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/" + clientID + "/" + countryCode + "/" + "auth_indication.txt")));
                            StringBuilder authFileBuilder = new StringBuilder();
                            while ((currentLine = authFileReader.readLine()) != null) {
                                authFileBuilder.append(currentLine);
                            }
                            authFileReader.close();
                            JSONObject authFileObj = new JSONObject(authFileBuilder.toString());
                            long lastModifiedTime = new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/" + clientID + "/" + countryCode + "/" + "auth_indication.txt").lastModified();
                            Date date = new Date();
                            date.setTime(lastModifiedTime);
                            String lastModifiedDate = new SimpleDateFormat("yyyyMMdd",new mInterfaceUtil().locale).format(date);
                            if (authFileObj.optString("validDevice").toString().equals("nostatus") || !lastModifiedDate.equals(new SimpleDateFormat("yyyyMMdd",new mInterfaceUtil().locale).format(new Date()))) {
                                /* AUTHENTICATION DATA REQUEST */
                                requestAuthenticationPath = new URL(cvsUrl + "/" + "get_auth_indication.aspx");
                                urlConObj = (HttpURLConnection)requestAuthenticationPath.openConnection();
                                urlConObj.setDoOutput(true);
                                urlConObj.setRequestMethod("POST");
                                urlConObj.setRequestProperty("CONTENT-TYPE", "application/json");
                                urlConObj.connect();

                                oStreamObj = new OutputStreamWriter(urlConObj.getOutputStream());
                                oStreamObj.write("<inputparam><context><sessionId>" + sessionID + "</sessionId><userId>" + userID + "</userId><client_id>" + clientID + "</client_id><locale_id>" + localeID + "</locale_id><country_code>" + countryCode + "</country_code></context></inputparam>");
                                oStreamObj.flush();
                                oStreamObj.close();
                                serverResponseObj = new StringBuilder();
                                responseReaderObj = new BufferedReader(new InputStreamReader(urlConObj.getInputStream()));
                                while ((currentLine = responseReaderObj.readLine()) != null) {
                                    serverResponseObj.append(currentLine);
                                }
                                responseReaderObj.close();
                                urlConObj.disconnect();
                                responseDataObj = new JSONObject(serverResponseObj.toString());

                                /* VALIDATE DEVICE REQUEST */
                                try {
                                    requestValidateDevicePath = new URL(clientUrl + "/security/validate_device.aspx");
                                    urlConObj = (HttpURLConnection)requestValidateDevicePath.openConnection();
                                    urlConObj.setDoOutput(true);
                                    urlConObj.setRequestMethod("POST");
                                    urlConObj.setRequestProperty("CONTENT-TYPE", "application/json");
                                    urlConObj.connect();
                                    oStreamObj = new OutputStreamWriter(urlConObj.getOutputStream());
                                    oStreamObj.write("<document><context><sessionId>" + sessionID + "</sessionId><userId>" + userID + "</userId><client_id>" + clientID + "</client_id><locale_id>" + localeID + "</locale_id><country_code>" + countryCode + "</country_code><inputparam><p_device_id>" + deviceID + "</p_device_id><p_company_id>" + clientID + "</p_company_id><p_country_code>" + countryCode + "</p_country_code></inputparam></context></document>");
                                    oStreamObj.flush();
                                    oStreamObj.close();
                                    serverResponseObj = new StringBuilder();
                                    responseReaderObj = new BufferedReader(new InputStreamReader(urlConObj.getInputStream()));
                                    while ((currentLine = responseReaderObj.readLine()) != null) {
                                        serverResponseObj.append(currentLine);
                                    }
                                    responseReaderObj.close();
                                    urlConObj.disconnect();
                                    Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder()
                                            .parse(new InputSource(new StringReader(serverResponseObj.toString())));
                                    responseDataObj = responseDataObj.put("validDevice", doc.getElementsByTagName("p_valid_device_ind").item(0).getTextContent());

                                    /* RESPONSE FOR AUTHENTICATION & VALIDATE DEVICE REQUESTS */
                                    writerObj = new BufferedWriter(new FileWriter(new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/" + clientID + "/" + countryCode + "/" + "auth_indication.txt")));
                                    writerObj.write(responseDataObj.toString());
                                    writerObj.flush();
                                    writerObj.close();
                                } catch (Exception ex) {
                                    responseDataObj = responseDataObj.put("validDevice", "nostatus");
                                    writerObj = new BufferedWriter(new FileWriter(new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/" + clientID + "/" + countryCode + "/" + "auth_indication.txt")));
                                    writerObj.write(responseDataObj.toString());
                                    writerObj.flush();
                                    writerObj.close();
                                }
                            }
                        } else {
                            /* AUTHENTICATION DATA REQUEST */
                            requestAuthenticationPath = new URL(cvsUrl + "/" + "get_auth_indication.aspx");
                            urlConObj = (HttpURLConnection)requestAuthenticationPath.openConnection();
                            urlConObj.setDoOutput(true);
                            urlConObj.setRequestMethod("POST");
                            urlConObj.setRequestProperty("CONTENT-TYPE", "application/json");
                            urlConObj.connect();

                            oStreamObj = new OutputStreamWriter(urlConObj.getOutputStream());
                            oStreamObj.write("<inputparam><context><sessionId>" + sessionID + "</sessionId><userId>" + userID + "</userId><client_id>" + clientID + "</client_id><locale_id>" + localeID + "</locale_id><country_code>" + countryCode + "</country_code></context></inputparam>");
                            oStreamObj.flush();
                            oStreamObj.close();
                            serverResponseObj = new StringBuilder();
                            responseReaderObj = new BufferedReader(new InputStreamReader(urlConObj.getInputStream()));
                            while ((currentLine = responseReaderObj.readLine()) != null) {
                                serverResponseObj.append(currentLine);
                            }
                            responseReaderObj.close();
                            urlConObj.disconnect();
                            responseDataObj = new JSONObject(serverResponseObj.toString());

                            /* VALIDATE DEVICE REQUEST */
                            try {
                                requestValidateDevicePath = new URL(clientUrl + "/security/validate_device.aspx");
                                urlConObj = (HttpURLConnection)requestValidateDevicePath.openConnection();
                                urlConObj.setDoOutput(true);
                                urlConObj.setRequestMethod("POST");
                                urlConObj.setRequestProperty("CONTENT-TYPE", "application/json");
                                urlConObj.connect();
                                oStreamObj = new OutputStreamWriter(urlConObj.getOutputStream());
                                oStreamObj.write("<document><context><sessionId>" + sessionID + "</sessionId><userId>" + userID + "</userId><client_id>" + clientID + "</client_id><locale_id>" + localeID + "</locale_id><country_code>" + countryCode + "</country_code><inputparam><p_device_id>" + deviceID + "</p_device_id><p_company_id>" + clientID + "</p_company_id><p_country_code>" + countryCode + "</p_country_code></inputparam></context></document>");
                                oStreamObj.flush();
                                oStreamObj.close();
                                serverResponseObj = new StringBuilder();
                                responseReaderObj = new BufferedReader(new InputStreamReader(urlConObj.getInputStream()));
                                while ((currentLine = responseReaderObj.readLine()) != null) {
                                    serverResponseObj.append(currentLine);
                                }
                                responseReaderObj.close();
                                urlConObj.disconnect();
                                Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder()
                                        .parse(new InputSource(new StringReader(serverResponseObj.toString())));
                                responseDataObj = responseDataObj.put("validDevice", doc.getElementsByTagName("p_valid_device_ind").item(0).getTextContent());

                                /* RESPONSE FOR AUTHENTICATION & VALIDATE DEVICE REQUESTS */
                                writerObj = new BufferedWriter(new FileWriter(new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/" + clientID + "/" + countryCode + "/" + "auth_indication.txt")));
                                writerObj.write(responseDataObj.toString());
                                writerObj.flush();
                                writerObj.close();
                            } catch (Exception ex) {
                                responseDataObj = responseDataObj.put("validDevice", "nostatus");
                                writerObj = new BufferedWriter(new FileWriter(new File(Environment.getExternalStorageDirectory(), "/" + mInterfaceUtil.packageName + "/" + clientID + "/" + countryCode + "/" + "auth_indication.txt")));
                                writerObj.write(responseDataObj.toString());
                                writerObj.flush();
                                writerObj.close();
                            }
                        }
                    }
                }
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    /* USER CLEARED APP FROM CACHE */
    @ Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        if (setChecksumTimerInterval != null) {
            setChecksumTimerInterval.cancel();
        }
        if (setQueueInterval != null) {
            setQueueInterval.cancel();
        }
        if (setTimerIntervel != null) {
            setTimerIntervel.cancel();
        }
        Intent restartService = new Intent(getApplicationContext(),
                this.getClass());
        restartService.setPackage(getPackageName());
        PendingIntent restartServicePI = PendingIntent.getService(
                getApplicationContext(), 1, restartService,
                PendingIntent.FLAG_ONE_SHOT);
        AlarmManager alarmService = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
        alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 2000, restartServicePI);
    }
    /* WHEN THE RAM IS LOW */
    @ Override
    public void onLowMemory() {
        super.onLowMemory();
        if (setChecksumTimerInterval != null) {
            setChecksumTimerInterval.cancel();
        }

        if (setQueueInterval != null) {
            setQueueInterval.cancel();
        }

        if (setTimerIntervel != null) {
            setTimerIntervel.cancel();
        }

        startService(new Intent(getApplicationContext(), mInterfaceService.class));
    }
    /* USER CLICK FORCE STOP IN SETTINGS */
    @ Override
    public void onDestroy() {
        super.onDestroy();
        if (setChecksumTimerInterval != null) {
            setChecksumTimerInterval.cancel();
        }

        if (setQueueInterval != null) {
            setQueueInterval.cancel();
        }

        if (setTimerIntervel != null) {
            setTimerIntervel.cancel();
        }

        startService(new Intent(getApplicationContext(), mInterfaceService.class));
    }
    public boolean isConnected() {
        ConnectivityManager online = (ConnectivityManager)getSystemService(this.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = online.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            return true;
        } else {
            return false;
        }
    }
}
