/**
 * Copyright (c) 2017-present, Stanislav Doskalenko - doskalenko.s@gmail.com
 * All rights reserved.
 *
 * This source code is licensed under the MIT-style license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * Based on Asim Malik android source code, copyright (c) 2015
 *
 **/

package com.reactnative.googlefit;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.Log;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.fitness.Fitness;
import com.google.android.gms.fitness.FitnessActivities;
import com.google.android.gms.fitness.FitnessOptions;
import com.google.android.gms.fitness.data.DataPoint;
import com.google.android.gms.fitness.data.DataSet;
import com.google.android.gms.fitness.data.DataSource;
import com.google.android.gms.fitness.data.DataType;
import com.google.android.gms.fitness.data.Field;
import com.google.android.gms.fitness.data.Session;
import com.google.android.gms.fitness.request.DataDeleteRequest;
import com.google.android.gms.fitness.request.SessionInsertRequest;
import com.google.android.gms.fitness.request.SessionReadRequest;
import com.google.android.gms.fitness.result.SessionReadResult;
import com.google.android.gms.fitness.result.SessionReadResponse;
import com.google.android.gms.tasks.Continuation;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;


import static java.text.DateFormat.getTimeInstance;

import java.text.DateFormat;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;

public class SleepHistory {

    private ReactContext mReactContext;
    private GoogleFitManager googleFitManager;

    private static final String TAG = "SleepHistory";

    public SleepHistory(ReactContext reactContext, GoogleFitManager googleFitManager){
        this.mReactContext = reactContext;
        this.googleFitManager = googleFitManager;
    }

    public void readSleepSession(long startTime, long endTime, final Callback successCallback) {

        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
        dateFormat.setTimeZone(TimeZone.getDefault());

        Log.i(TAG, "Range Start: " + dateFormat.format(startTime));
        Log.i(TAG, "Range End: " + dateFormat.format(endTime));

        final WritableArray results = Arguments.createArray();

        final SessionReadRequest readRequest = new SessionReadRequest.Builder()
                                                            .setTimeInterval(startTime, endTime, TimeUnit.MILLISECONDS)
                                                            .read(DataType.TYPE_ACTIVITY_SEGMENT)
                                                            .readSessionsFromAllApps()
                                                            .enableServerQueries()
                                                            .build();

        PendingResult<SessionReadResult> readPendingResult = Fitness.SessionsApi
                                                            .readSession(googleFitManager.getGoogleApiClient(), readRequest);

        readPendingResult.setResultCallback(new ResultCallback<SessionReadResult>() {
            @Override
            public void onResult(@NonNull SessionReadResult response) {
                WritableArray map = Arguments.createArray();
                if (response.getSessions().size() > 0) {
                    Log.i(TAG, "  +++ Number of sessions: " + response.getSessions().size());
                    for (Session session : response.getSessions()) {
                        WritableMap stepMap = Arguments.createMap();
                        stepMap.putDouble("startDate", session.getStartTime(TimeUnit.MILLISECONDS));
                        stepMap.putDouble("endDate", session.getEndTime(TimeUnit.MILLISECONDS));
                        stepMap.putString("identifier", session.getIdentifier().toString());
                        stepMap.putString("activity", session.getActivity().toString());
                        stepMap.putString("appPackageName", session.getAppPackageName().toString());
                        map.pushMap(stepMap);
                        Log.i(TAG, "  session: " + session);
                    }
                }
                successCallback.invoke(map);
            }
        }, 1, TimeUnit.MINUTES);
    }

    public void saveSleepSession(long startTime, long endTime, final Callback successCallback) {

        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
        dateFormat.setTimeZone(TimeZone.getDefault());

        String sessionName = "sleep";
        String description = "manually save sleep data";
        String identifier = Long.toString(startTime);

        Log.i(TAG, "Range Start: " + dateFormat.format(startTime));
        Log.i(TAG, "Range End: " + dateFormat.format(endTime));

        final WritableArray results = Arguments.createArray();

        // Create a session with metadata about the activity.
        Session session = new Session.Builder()
                            .setName(sessionName)
                            .setDescription(description)
                            .setIdentifier(identifier)
                            .setActivity(FitnessActivities.SLEEP)
                            .setStartTime(startTime, TimeUnit.MILLISECONDS)
                            .setEndTime(endTime, TimeUnit.MILLISECONDS)
                            .build();


        //Build a session insert request
        SessionInsertRequest insertRequest = new SessionInsertRequest.Builder()
                                                .setSession(session)
                                                .build();

        PendingResult<Status> saveDataStatus = Fitness.SessionsApi
                                                .insertSession(googleFitManager.getGoogleApiClient(), insertRequest);

        saveDataStatus.setResultCallback(new ResultCallback<Status>() {
            @Override
            public void onResult(@NonNull Status response) {
                Log.i(TAG, "Session Response: " + response);
                WritableMap result = Arguments.createMap();
                if (response.isSuccess()) {
                    result.putBoolean("isSuccess", response.isSuccess());
                } 
                successCallback.invoke(result);
            }
        }, 1, TimeUnit.MINUTES);
    }

}
