com.rsltc.profiledata.main.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.rsltc.profiledata.main.MainActivity.java

Source

/*
 * Copyright (C) 2016 Google, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.rsltc.profiledata.main;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.text.InputType;
import android.view.Menu;
import android.view.MenuItem;

import android.util.Log;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.Scopes;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.Scope;
import com.rsltc.profiledata.DailyHeartRate;
import com.rsltc.profiledata.DateUtils;
import com.rsltc.profiledata.DistanceSummary;
import com.rsltc.profiledata.HealthConstants;
import com.rsltc.profiledata.HealthStatValidityChecker;
import com.rsltc.profiledata.InfoType;
import com.rsltc.profiledata.JsonObjectsFromType;
import com.rsltc.profiledata.MSCloudLiveIdCredentials;
import com.rsltc.profiledata.MSHealthRestClient;
import com.rsltc.profiledata.MathUtil;
import com.rsltc.profiledata.MicrosoftRestClient;
import com.rsltc.profiledata.ProcessSummaries;
import com.rsltc.profiledata.R;
import com.rsltc.profiledata.SpeedSummary;
import com.rsltc.profiledata.Summary;
import com.rsltc.profiledata.User;
import com.google.android.gms.fitness.Fitness;
import com.google.android.gms.fitness.data.Bucket;
import com.google.android.gms.fitness.data.DataPoint;
import com.google.android.gms.fitness.data.DataSet;
import com.google.android.gms.fitness.data.DataType;
import com.google.android.gms.fitness.data.Field;
import com.google.android.gms.fitness.request.DataReadRequest;
import com.google.android.gms.fitness.result.DataReadResult;
import com.loopj.android.http.JsonHttpResponseHandler;
import com.loopj.android.http.RequestParams;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

import cz.msebera.android.httpclient.Header;

import static java.text.DateFormat.getDateInstance;
import static java.text.DateFormat.getTimeInstance;

public class MainActivity extends AppCompatActivity {
    public static final String TAG = "BasicHistoryApi";
    private static final int REQUEST_OAUTH = 1;
    private static final String DATE_FORMAT = "yyyy.MM.dd HH:mm:ss";
    private Activity thisActivity = this;
    private final String scopes = "mshealth.ReadDevices mshealth.ReadActivityHistory mshealth.ReadActivityLocation mshealth.ReadDevices";
    private final String baseHealthUri = "api.microsofthealth.net/v1/me/";
    private final String redirectUri = "https://login.live.com/oauth20_desktop.srf";
    private final String clientId = "000000004417D217";
    private MSCloudLiveIdCredentials creds = new MSCloudLiveIdCredentials();

    /**
     * Track whether an authorization activity is stacking over the current activity, i.e. when
     * a known auth error is being resolved, such as showing the account chooser or presenting a
     * consent dialog. This avoids common duplications as might happen on screen rotations, etc.
     */
    private static final String AUTH_PENDING = "auth_state_pending";
    private static boolean authInProgress = false;

    public static GoogleApiClient mClient = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button loginButton = (Button) findViewById(R.id.button);
        loginButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    AlertDialog.Builder alert = new AlertDialog.Builder(thisActivity);
                    alert.setTitle("Title here");

                    StringBuilder query = new StringBuilder();

                    query.append("redirect_uri=" + URLEncoder.encode(redirectUri, "utf-8"));
                    query.append("&client_id=" + URLEncoder.encode(clientId, "utf-8"));
                    query.append("&scope=" + URLEncoder.encode(scopes, "utf-8"));

                    query.append("&response_type=code");
                    URI uri = new URI("https://login.live.com/oauth20_authorize.srf?" + query.toString());

                    URL url = uri.toURL();

                    final WebView wv = new WebView(thisActivity);

                    WebSettings webSettings = wv.getSettings();
                    webSettings.setJavaScriptEnabled(true);
                    wv.loadUrl(url.toString());
                    wv.setWebViewClient(new WebViewClient() {
                        @Override
                        public boolean shouldOverrideUrlLoading(WebView view, String location) {
                            Log.e(TAG, location);
                            // TODO: extract to method
                            try {
                                URL url = new URL(location);

                                if (url.getPath().equalsIgnoreCase("/oauth20_desktop.srf")) {
                                    System.out.println("Dit werkt al!");
                                    System.out.println(url.getQuery());
                                    Map<String, List<String>> result = splitQuery(url);
                                    if (result.containsKey("code")) {
                                        System.out.println("bevat code");
                                        if (result.containsKey("error")) {
                                            System.out.println(String.format("{0}\r\n{1}", result.get("error"),
                                                    result.get("errorDesc")));
                                        }
                                        System.out.println(result.get("code").get(0));
                                        String tokenError = GetToken(result.get("code").get(0), false);
                                        if (tokenError == null || "".equals(tokenError)) {
                                            System.out.println("Successful sign-in!");
                                            Log.e(TAG, "Successful sign-in!");
                                        } else {
                                            Log.e(TAG, "tokenError: " + tokenError);
                                        }
                                    } else {
                                        System.out.println("Successful sign-out!");
                                    }
                                }
                            } catch (IOException | URISyntaxException e) {
                                e.printStackTrace();
                            }

                            view.loadUrl(location);

                            return true;
                        }
                    });
                    LinearLayout linearLayout = new LinearLayout(thisActivity);
                    linearLayout.setMinimumHeight(500);
                    ArrayList<View> views = new ArrayList<View>();
                    views.add(wv);
                    linearLayout.addView(wv);
                    EditText text = new EditText(thisActivity);
                    text.setVisibility(View.GONE);
                    linearLayout.addView(text);
                    alert.setView(linearLayout);
                    alert.setNegativeButton("Close", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.dismiss();
                        }
                    });
                    alert.show();
                } catch (Exception e) {
                    Log.e(TAG, "dd");
                }
            }
        });
        Button showProfile = (Button) findViewById(R.id.button2);
        showProfile.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showProfile();
            }
        });
        Button showSummmary = (Button) findViewById(R.id.button3);
        showSummmary.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showSummaries();
            }
        });

        if (savedInstanceState != null)

        {
            authInProgress = savedInstanceState.getBoolean(AUTH_PENDING);
        }

        buildFitnessClient();
    }

    class PaginatedRequestTask extends AsyncTask<Object, Void, JsonObjectsFromType> {
        final boolean[] hasNext = { true };
        final List<JSONObject>[] jsonObjectList = new List[] { null };

        protected JsonObjectsFromType doInBackground(Object... args) {
            if (args.length != 2) {
                Log.e(TAG, "Task Cannot be executed");
            }
            final String[] nextPageURL = { (String) args[0] };
            jsonObjectList[0] = (List<JSONObject>) args[1];
            InfoType type = (InfoType) args[2];
            JsonObjectsFromType result = new JsonObjectsFromType(type);
            try {

                while (hasNext[0]) {
                    try {
                        URI uri = new URI(nextPageURL[0]);

                        MSHealthRestClient.getAbs(uri.toURL().toString(), new JsonHttpResponseHandler() {
                            @Override
                            public void onSuccess(int statusCode, Header[] headers, final JSONObject response) {
                                Log.e(TAG, response.toString());
                                jsonObjectList[0].add(response);
                                if (hasNext[0] = response.has("nextPage")) {
                                    try {
                                        nextPageURL[0] = response.getString("nextPage");
                                    } catch (JSONException e) {
                                        Log.e(TAG, "Something went wrong when looking for nextPage");
                                        hasNext[0] = false;
                                    }
                                }

                            }

                            @Override
                            public void onFailure(int d, Header[] headers, String mess, Throwable e) {
                                Log.e(TAG, e.getMessage());
                            }

                            @Override
                            public void onFailure(int statusCode, Header[] headers, Throwable throwable,
                                    JSONObject errorResponse) {
                                Log.e(TAG, throwable.getMessage());
                            }
                        }, creds);

                    } catch (Exception ignored) {
                    }

                }
            } catch (Exception ignored) {

            } finally {
                result.setJsonObjectList(jsonObjectList[0]);
                return result;
            }

        }

        protected void onProgressUpdate(Integer... progress) {
            Log.i(TAG, "Still loading pages");
        }

        protected void onPostExecute(JsonObjectsFromType result) {
            //            showSaveDialog(jsonObjectList[0]);
            new ProcessSummaries().execute(result);
        }

    }

    private void PerformRequest(String relativePath, RequestParams params, final InfoType type) {
        MSHealthRestClient.get(relativePath, params, new JsonHttpResponseHandler() {
            @Override
            public void onSuccess(int statusCode, Header[] headers, final JSONObject response) {
                try {
                    Log.e(TAG, response.toString());
                    final List<JSONObject> jsonObjectList = new ArrayList<>();
                    jsonObjectList.add(response);
                    if (response.has("nextPage")) {
                        String nextPageURL = (String) response.get("nextPage");
                        // TODO: make async again
                        new PaginatedRequestTask().execute(nextPageURL, jsonObjectList, type);
                    } else {
                        JsonObjectsFromType jsonObjectsFromType = new JsonObjectsFromType(type);
                        jsonObjectsFromType.setJsonObjectList(jsonObjectList);
                        new ProcessSummaries().execute(jsonObjectsFromType);
                        //                        showSaveDialog(jsonObjectList);
                    }
                } catch (Exception e) {
                    Log.i(TAG, "");
                }
            }

            @Override
            public void onFailure(int d, Header[] headers, String mess, Throwable e) {
                Log.e(TAG, e.getMessage());
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject errorResponse) {
                super.onFailure(statusCode, headers, throwable, errorResponse);
            }
        }, creds);
    }

    private void showSaveDialog(final List<JSONObject> jsonObjectList) {
        AlertDialog.Builder builder = new AlertDialog.Builder(thisActivity);
        builder.setTitle("Dataset title");

        final EditText input = new EditText(thisActivity);
        input.setInputType(InputType.TYPE_CLASS_TEXT);
        builder.setView(input);

        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                final String m_Text = input.getText().toString();
                Runnable r = new Runnable() {
                    @Override
                    public void run() {
                        exportFile(jsonObjectList, m_Text);
                    }
                };

                Thread t = new Thread(r);
                t.start();
            }
        });
        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });

        builder.show();
    }

    public void showProfile() {
        PerformRequest("Profile", new RequestParams(), InfoType.USER_STATS);
    }

    public void showSummaries() {

        RequestParams params = new RequestParams();
        TimeZone tz = TimeZone.getTimeZone("UTC");
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
        df.setTimeZone(tz);
        String nowAsISOBefore = df.format(new Date("02/01/2016"));
        String nowAsISO = df.format(new Date());

        params.add("startTime", nowAsISOBefore);
        params.add("endTime", nowAsISO);

        params.add("maxPagesize", "48");
        PerformRequest("Summaries/Daily", params, InfoType.BPM);
    }

    public static Map<String, List<String>> splitQuery(URL url) throws UnsupportedEncodingException {
        final Map<String, List<String>> query_pairs = new LinkedHashMap<String, List<String>>();
        final String[] pairs = url.getQuery().split("&");
        for (String pair : pairs) {
            final int idx = pair.indexOf("=");
            final String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx), "UTF-8") : pair;
            if (!query_pairs.containsKey(key)) {
                query_pairs.put(key, new LinkedList<String>());
            }
            final String value = idx > 0 && pair.length() > idx + 1
                    ? URLDecoder.decode(pair.substring(idx + 1), "UTF-8")
                    : null;
            query_pairs.get(key).add(value);
        }
        return query_pairs;
    }

    private String GetToken(String code, boolean isRefresh) throws IOException, URISyntaxException {
        RequestParams params = new RequestParams();
        params.add("redirect_uri", redirectUri);
        params.add("client_id", clientId);
        params.add("scope", scopes);
        if (isRefresh) {
            params.add("refresh_token", code);
            params.add("grant_type", "refresh_token");

        } else {
            params.add("code", code);
            params.add("grant_type", "authorization_code");

        }
        MicrosoftRestClient.get("", params, new JsonHttpResponseHandler() {
            @Override
            public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
                //                Log.e(TAG, response.toString());
                try {
                    if (response.has("access_token")) {
                        creds.setAccessToken((String) response.get("access_token"));
                        System.out.println(creds.getAccessToken());
                    }
                    if (response.has("expires_in")) {
                        creds.setExpiresIn((Integer) response.get("expires_in"));
                    }
                    if (response.has("refresh_token")) {
                        creds.setRefreshToken((String) response.get("refresh_token"));
                    }
                    if (response.has("error")) {
                        // TODO: do something with error
                        //                    return (String) response.get("error");
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });
        return null;
    }

    private void buildFitnessClient() {
        mClient = new GoogleApiClient.Builder(this).addApi(Fitness.HISTORY_API)
                .addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ)).addScope(new Scope(Scopes.FITNESS_BODY_READ))
                .addScope(new Scope(Scopes.FITNESS_LOCATION_READ))
                .addScope(new Scope(Scopes.FITNESS_NUTRITION_READ))
                .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
                    @Override
                    public void onConnected(Bundle bundle) {
                        Log.i(TAG, "Connected!!!");
                        new InsertAndVerifyDataTask().execute();
                    }

                    @Override
                    public void onConnectionSuspended(int i) {
                        if (i == ConnectionCallbacks.CAUSE_NETWORK_LOST) {
                            Log.i(TAG, "Connection lost.  Cause: Network Lost.");
                        } else if (i == ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
                            Log.i(TAG, "Connection lost.  Reason: Service Disconnected");
                        }
                    }
                }).enableAutoManage(this, 0, new GoogleApiClient.OnConnectionFailedListener() {
                    @Override
                    public void onConnectionFailed(ConnectionResult result) {
                        Log.i(TAG, "Google Play services connection failed. Cause: " + result.toString());
                        Snackbar.make(MainActivity.this.findViewById(R.id.main_activity_view),
                                "Exception while connecting to Google Play services: " + result.getErrorMessage(),
                                Snackbar.LENGTH_INDEFINITE).show();
                    }
                }).build();
    }

    private class InsertAndVerifyDataTask extends AsyncTask<Void, Void, Void> {
        protected Void doInBackground(Void... params) {
            DataReadRequest readRequest = queryFitnessData();

            DataReadResult dataReadResult = Fitness.HistoryApi.readData(mClient, readRequest).await(1,
                    TimeUnit.MINUTES);

            processData(dataReadResult, InfoType.DISTANCE_SUMMARY);

            return null;
        }
    }

    public static DataReadRequest queryFitnessData() {
        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
        Date now = new Date();
        cal.setTime(now);
        //        cal.add(Calendar.YEAR, -1);
        //        cal.set(2015,7,20);
        long endTime = cal.getTimeInMillis();
        cal.add(Calendar.YEAR, -1);

        long startTime = cal.getTimeInMillis();

        java.text.DateFormat dateFormat = getDateInstance();
        Log.i(TAG, "Range Start: " + dateFormat.format(startTime));
        Log.i(TAG, "Range End: " + dateFormat.format(endTime));

        DataReadRequest readRequest = new DataReadRequest.Builder()

                .aggregate(DataType.TYPE_DISTANCE_DELTA, DataType.AGGREGATE_DISTANCE_DELTA)

                //                .read(DataType.TYPE_WEIGHT)
                //                .read(DataType.TYPE_HEIGHT)
                //                .read(DataType.TYPE_HEART_RATE_BPM)
                .bucketByActivitySegment(5, TimeUnit.MINUTES)
                //                .bucketByActivityType(1, TimeUnit.SECONDS)
                //                .bucketByTime(1, TimeUnit.DAYS)
                .setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS).build();

        return readRequest;
    }

    public static void processData(DataReadResult dataReadResult, InfoType type) {
        Log.i(TAG, dataReadResult.toString());
        Calendar calendar = Calendar.getInstance();
        if (type == InfoType.SPEED_SUMMARY) {
            Map<String, SpeedSummary> speedsummaries = new HashMap<String, SpeedSummary>();
            speedsummaries.put(HealthConstants.ActivityType.ACTIVITY_BIKING,
                    new SpeedSummary(HealthConstants.ActivityType.ACTIVITY_BIKING));
            speedsummaries.put(HealthConstants.ActivityType.ACTIVITY_RUNNING,
                    new SpeedSummary(HealthConstants.ActivityType.ACTIVITY_RUNNING));
            speedsummaries.put(HealthConstants.ActivityType.ACTIVITY_WALKING,
                    new SpeedSummary(HealthConstants.ActivityType.ACTIVITY_WALKING));
            String currentType = "";
            if (dataReadResult.getBuckets().size() > 0) {
                Log.i(TAG, "Number of returned buckets of DataSets is: " + dataReadResult.getBuckets().size());
                for (Bucket bucket : dataReadResult.getBuckets()) {
                    if (bucket.getDataSets().get(0).getDataPoints().size() > 0) {
                        if (bucket.getActivity().equals("running")) {
                            currentType = HealthConstants.ActivityType.ACTIVITY_RUNNING;
                        } else if (bucket.getActivity().equals("walking")) {
                            currentType = HealthConstants.ActivityType.ACTIVITY_WALKING;
                        } else if (bucket.getActivity().equals("biking")) {
                            currentType = HealthConstants.ActivityType.ACTIVITY_BIKING;
                        } else {
                            Log.e(TAG, "Activity type not processed: " + bucket.getActivity());
                            continue;
                        }
                        Log.e(TAG, "Bucket : " + bucket.getActivity());
                        calendar.setTimeInMillis(bucket.getStartTime(TimeUnit.MILLISECONDS));
                        Log.i(TAG, "Time: " + calendar.getTime());
                        List<DataSet> dataSets = bucket.getDataSets();
                        for (DataSet dataSet : dataSets) {
                            processSpeedSumary(dataSet, type, speedsummaries.get(currentType), currentType);
                        }
                    }
                }
                //            } else if (dataReadResult.getDataSets().size() > 0) {
                //                Log.i(TAG, "Number of returned DataSets is: "
                //                        + dataReadResult.getDataSets().size());
                //                for (DataSet dataSet : dataReadResult.getDataSets()) {
                //                    processDataSet(dataSet, type);
                //                }
            }

            Log.e(TAG, speedsummaries.get(HealthConstants.ActivityType.ACTIVITY_BIKING).toString());
            Log.e(TAG, speedsummaries.get(HealthConstants.ActivityType.ACTIVITY_WALKING).toString());
            Log.e(TAG, speedsummaries.get(HealthConstants.ActivityType.ACTIVITY_RUNNING).toString());
        } else if (type == InfoType.DISTANCE_SUMMARY) {
            Map<String, DistanceSummary> distanceSummmaries = new HashMap<>();
            distanceSummmaries.put(HealthConstants.ActivityType.ACTIVITY_BIKING,
                    new DistanceSummary(HealthConstants.ActivityType.ACTIVITY_BIKING));
            distanceSummmaries.put(HealthConstants.ActivityType.ACTIVITY_RUNNING,
                    new DistanceSummary(HealthConstants.ActivityType.ACTIVITY_RUNNING));
            distanceSummmaries.put(HealthConstants.ActivityType.ACTIVITY_WALKING,
                    new DistanceSummary(HealthConstants.ActivityType.ACTIVITY_WALKING));
            String currentType = "";
            if (dataReadResult.getBuckets().size() > 0) {
                Log.i(TAG, "Number of returned buckets of DataSets is: " + dataReadResult.getBuckets().size());
                for (Bucket bucket : dataReadResult.getBuckets()) {
                    if (bucket.getDataSets().get(0).getDataPoints().size() > 0) {
                        if (bucket.getActivity().equals("running")) {
                            currentType = HealthConstants.ActivityType.ACTIVITY_RUNNING;
                        } else if (bucket.getActivity().equals("walking")) {
                            currentType = HealthConstants.ActivityType.ACTIVITY_WALKING;
                        } else if (bucket.getActivity().equals("biking")) {
                            currentType = HealthConstants.ActivityType.ACTIVITY_BIKING;
                        } else {
                            Log.e(TAG, "Activity type not processed: " + bucket.getActivity());
                            continue;
                        }
                        Log.e(TAG, "Bucket : " + bucket.getActivity());
                        calendar.setTimeInMillis(bucket.getStartTime(TimeUnit.MILLISECONDS));
                        Log.i(TAG, "Time: " + calendar.getTime());
                        List<DataSet> dataSets = bucket.getDataSets();
                        for (DataSet dataSet : dataSets) {
                            processDistanceSummary(dataSet, type, distanceSummmaries.get(currentType));
                        }
                    }
                }
            }
            Log.e(TAG, distanceSummmaries.get(HealthConstants.ActivityType.ACTIVITY_BIKING).toString());
            Log.e(TAG, distanceSummmaries.get(HealthConstants.ActivityType.ACTIVITY_WALKING).toString());
            Log.e(TAG, distanceSummmaries.get(HealthConstants.ActivityType.ACTIVITY_RUNNING).toString());
        } else {
            if (dataReadResult.getBuckets().size() > 0) {
                Log.i(TAG, "Number of returned buckets of DataSets is: " + dataReadResult.getBuckets().size());
                for (Bucket bucket : dataReadResult.getBuckets()) {
                    if (bucket.getDataSets().get(0).getDataPoints().size() > 0) {
                        Log.e(TAG, "Bucket : " + bucket.getActivity());
                        calendar.setTimeInMillis(bucket.getStartTime(TimeUnit.MILLISECONDS));
                        Log.i(TAG, "Time: " + calendar.getTime());
                        List<DataSet> dataSets = bucket.getDataSets();
                        for (DataSet dataSet : dataSets) {
                            processDataSet(dataSet, type);
                        }
                    }
                }
            } else if (dataReadResult.getDataSets().size() > 0) {
                Log.i(TAG, "Number of returned DataSets is: " + dataReadResult.getDataSets().size());
                for (DataSet dataSet : dataReadResult.getDataSets()) {
                    processDataSet(dataSet, type);
                }
            }
        }
    }

    private static void processSpeedSumary(DataSet dataSet, InfoType type, SpeedSummary summary,
            String currentType) {
        Calendar calendar = Calendar.getInstance();
        for (DataPoint dp : dataSet.getDataPoints()) {
            Float min = null, max = null, avg = null;
            Log.i(TAG, "Data point:");
            Log.i(TAG, "\tType: " + dp.getDataType().getName());
            Long startTime = dp.getStartTime(TimeUnit.MILLISECONDS);
            calendar.setTimeInMillis(startTime);
            Log.i(TAG, "\tStart: " + calendar.getTime());
            Long stopTime = dp.getEndTime(TimeUnit.MILLISECONDS);
            calendar.setTimeInMillis(stopTime);
            Log.i(TAG, "\tStop: " + calendar.getTime());

            Long duration = stopTime - startTime;
            Log.i(TAG, "Timezone: " + calendar.getTimeZone().getDisplayName());
            for (Field field : dp.getDataType().getFields()) {
                Log.i(TAG, "\tField: " + field.getName() + " Value: " + dp.getValue(field));
                if (field.equals(Field.FIELD_AVERAGE)) {
                    avg = dp.getValue(field).asFloat();
                } else if (field.equals(Field.FIELD_MIN)) {
                    min = dp.getValue(field).asFloat();
                } else if (field.equals(Field.FIELD_MAX)) {
                    max = dp.getValue(field).asFloat();
                } else {
                    Log.e(TAG, "Unsupported field found");
                }
            }
            boolean valid = false;
            if (min != null && max != null && avg != null) {
                // TODO: build check for speeds
                if (!(valid = HealthStatValidityChecker.checkAvgSpeed(avg, currentType))) {
                    avg = (max + min) / 2;
                    valid = HealthStatValidityChecker.checkAvgSpeed(avg, currentType);
                }
            }
            if (valid) {
                summary.setMaxSpeedIfGreater(max);
                summary.setMinSpeedIfSmaller(min);
                summary.setMaxDurationIfLonger(duration);
                summary.setMinDurationIfShorter(duration);
                double count = summary.getCount();
                summary.setAvgSpeed((summary.getAvgSpeed() * count + avg) / (count + 1));
                summary.setAvgDuration((float) ((summary.getAvgDuration() * count + duration) / (count + 1)));
                summary.increaseCount();
            }

        }
    }

    private static void processDataSet(DataSet dataSet, InfoType type) {
        Log.i(TAG, "Data returned for Data type: " + dataSet.getDataType().getName());
        Calendar calendar = Calendar.getInstance();
        User user = new User();
        for (DataPoint dp : dataSet.getDataPoints()) {
            if (type == InfoType.BPM) {
                Float min = null, max = null, avg = null;
                Log.i(TAG, "Data point:");
                Log.i(TAG, "\tType: " + dp.getDataType().getName());
                calendar.setTimeInMillis(dp.getStartTime(TimeUnit.MILLISECONDS));
                Log.i(TAG, "\tStart: " + calendar.getTime());
                calendar.setTimeInMillis(dp.getEndTime(TimeUnit.MILLISECONDS));
                Log.i(TAG, "\tStop: " + calendar.getTime());
                Log.i(TAG, "Timezone: " + calendar.getTimeZone().getDisplayName());
                for (Field field : dp.getDataType().getFields()) {
                    Log.i(TAG, "\tField: " + field.getName() + " Value: " + dp.getValue(field));
                    if (field.equals(Field.FIELD_AVERAGE)) {
                        avg = dp.getValue(field).asFloat();
                    } else if (field.equals(Field.FIELD_MIN)) {
                        min = dp.getValue(field).asFloat();
                    } else if (field.equals(Field.FIELD_MAX)) {
                        max = dp.getValue(field).asFloat();
                    } else {
                        Log.e(TAG, "Unsupported field found");
                    }
                }
                boolean valid = true;
                if (min != null && max != null && avg != null) {
                    if (!HealthStatValidityChecker.checkIfNormal(avg, type)) {
                        avg = (max + min) / 2;
                        valid = HealthStatValidityChecker.checkIfNormal(avg, type);
                    }
                } else {
                    valid = false;
                }
                DailyHeartRate dailyHeartRate = new DailyHeartRate(avg != null ? avg : -1, max != null ? max : -1,
                        min != null ? min : -1, valid, DateUtils.dateToDateRelated(calendar));
            } else if (type == InfoType.USER_STATS) {
                Log.e(TAG, dp.toString());
                Log.i(TAG, "Data point:");
                Log.i(TAG, "\tType: " + dp.getDataType().getName());
                DataType datatype = dp.getDataType();
                calendar.setTimeInMillis(dp.getStartTime(TimeUnit.MILLISECONDS));
                String dayOfMeasurement = DateUtils.dateToDateRelated(calendar);
                if (datatype.equals(DataType.TYPE_HEIGHT)) {
                    Log.e(TAG, "I have height");
                    user.setHeight(dp.getValue(dp.getDataType().getFields().get(0)).asFloat());
                } else {
                    Log.e(TAG, "I have weight");
                    user.setWeight(MathUtil.round(dp.getValue(dp.getDataType().getFields().get(0)).asFloat(), 3));
                }

                Log.i(TAG, "\tStart: " + calendar.getTime());
                calendar.setTimeInMillis(dp.getEndTime(TimeUnit.MILLISECONDS));
                Log.i(TAG, "\tStop: " + calendar.getTime());
                for (Field field : dp.getDataType().getFields()) {
                    Log.i(TAG, field.getName() + " " + dp.getValue(field));
                }

            }
        }
        if (type == InfoType.USER_STATS) {
            //persist the user
            Log.i(TAG, user.toString());
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_delete_data) {
            //            deleteData();
            return true;
        } else if (id == R.id.action_update_data) {
            //            Intent intent = new Intent(MainActivity.this, MainActivity2.class);
            //            MainActivity.this.startActivity(intent);
        }
        return super.onOptionsItemSelected(item);
    }

    private void exportFile(List<JSONObject> jsonObjects, String dataset_name) {
        final String date = new SimpleDateFormat("yyyyMMdd-HHmmss", Locale.getDefault()).format(new Date());
        final String filename = String.format("%s_%s.txt", dataset_name, date);

        final String directory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/AndroidTesting/";

        final File logfile = new File(directory, filename);
        final File logPath = logfile.getParentFile();

        if (!logPath.isDirectory() && !logPath.mkdirs()) {
            Log.e("SensorDashbaord", "Could not create directory for log files");
        }

        try {
            FileWriter filewriter = new FileWriter(logfile);
            BufferedWriter bw = new BufferedWriter(filewriter);

            //            for (JSONObject object : jsonObjects) {
            bw.write(jsonObjects.toString());
            //            }
            bw.flush();
            bw.close();

            Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
            emailIntent.setType("*/*");

            emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, dataset_name + ".csv");
            emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(logfile));
            startActivity(Intent.createChooser(emailIntent, "Send mail..."));

            Log.i(TAG, "export finished!");
        } catch (IOException ioe) {
            Log.e(TAG, "IOException while writing Logfile");
            Log.e("Enias", ioe.getMessage());
        }
    }

    private static void processDistanceSummary(DataSet dataSet, InfoType type, DistanceSummary summary) {
        Calendar calendar = Calendar.getInstance();
        for (DataPoint dp : dataSet.getDataPoints()) {
            Float distance = null;
            Log.i(TAG, "Data point:");
            Log.i(TAG, "\tType: " + dp.getDataType().getName());
            Long startTime = dp.getStartTime(TimeUnit.MILLISECONDS);
            calendar.setTimeInMillis(startTime);
            Log.i(TAG, "\tStart: " + calendar.getTime());
            Long stopTime = dp.getEndTime(TimeUnit.MILLISECONDS);
            calendar.setTimeInMillis(stopTime);
            Log.i(TAG, "\tStop: " + calendar.getTime());

            Long duration = stopTime - startTime;
            Log.i(TAG, "Timezone: " + calendar.getTimeZone().getDisplayName());
            for (Field field : dp.getDataType().getFields()) {
                Log.i(TAG, "\tField: " + field.getName() + " Value: " + dp.getValue(field));
                if (field.equals(Field.FIELD_DISTANCE)) {
                    distance = dp.getValue(field).asFloat();
                } else {
                    Log.e(TAG, "Unsupported field found");
                }
            }
            boolean valid = false;
            if (distance != null) {
                valid = HealthStatValidityChecker.checkIfNormalDistance(distance, type);
            }
            if (valid) {
                summary.setMaxDistanceIfGreater(distance);
                summary.setMinDistanceIfSmaller(distance);
                summary.setMaxDurationIfLonger(duration);
                summary.setMinDurationIfShorter(duration);
                double count = summary.getCount();
                summary.setAvgDistance((summary.getAvgDistance() * count + distance) / (count + 1));
                summary.setAvgDuration((float) ((summary.getAvgDuration() * count + duration) / (count + 1)));
                summary.increaseCount();
            }
        }
    }
}