package com.algobase.activity;

import android.app.Activity;

import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.DialogInterface;

import android.os.Bundle;
import android.os.IBinder;
import android.os.Handler;

import android.util.Log;

import android.view.View;
import android.view.View.OnClickListener;

import android.widget.ExpandableListView;
import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;
import android.widget.Button;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

import com.algobase.share.dialog.*;
import com.algobase.share.bluetooth.*;

import com.algobase.stracks.R;

/*
import androidx.fragment.app.FragmentActivity;
*/


/* For a given BLE device, this Activity provides the user interface to 
   connect, display data, and display GATT services and characteristics 
   supported by the device.  The Activity communicates with 
   {@code BluetoothLeService}, which in turn interacts with the
   Bluetooth LE API.
 */

//public class BluetoothControlActivity extends FragmentActivity 

public class BluetoothControlActivity extends Activity 
{

  private final static String TAG = "BLE Sample";

  public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
  public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";

  private Handler handler = new Handler();

  private TextView connectionState;
  private TextView dataField;
  private Button connectButton;

  private String deviceName;
  private String deviceAddress;
  private ExpandableListView gattServicesList;

  private BluetoothLeService bleService;

  private ArrayList<ArrayList<BluetoothGattCharacteristic>> 
      gattCharacteristics =
          new ArrayList<ArrayList<BluetoothGattCharacteristic>>();

  private boolean connected = false;
  private BluetoothGattCharacteristic notifyCharacteristic;

  private final String LIST_NAME = "NAME";
  private final String LIST_UUID = "UUID";

  // Code to manage Service lifecycle.
  private final ServiceConnection serviceConnection = new ServiceConnection()
  {

    @Override
    public void onServiceConnected(ComponentName componentName,IBinder service) 
    {
      Log.i(TAG, "onServiceConnected");

      bleService = BluetoothLeService.getService(service);

      if (bleService == null)
      { showToast("onServiceConnected: service == null");
        Log.d(TAG, "Could not initialize BT Service");
        return;
      }

      boolean result = bleService.connect(deviceAddress,0);

      showToast("onServiceConnected: service != null");
      Log.i(TAG, "Connect request result=" + result);
    }


    @Override
    public void onServiceDisconnected(ComponentName componentName) {
      Log.i(TAG, "onServiceDisConnected");
      bleService = null;
    }
  };


  // Handles various events fired by the Service.
  // ACTION_CONNECTED: connected to a GATT server.
  // ACTION_DISCONNECTED: disconnected from a GATT server.
  // ACTION_SERVICES_DISCOVERED: discovered GATT services.
  // ACTION_DATA_AVAILABLE: received data from the device.  
  // This can be a result of read or notification operations.

  private final BroadcastReceiver gattUpdateReceiver = 
     new BroadcastReceiver() {

      @Override
      public void onReceive(Context context, Intent intent) {

        final String action = intent.getAction();
        Log.i(TAG,"onReceive: action = " + action);

        if (action.equals(BluetoothLeService.ACTION_CONNECTED)) {
           connected = true;
           connectionState.setText("connected");
           connectButton.setText("disconnect");
           return;
        }  

        if (action.equals(BluetoothLeService.ACTION_DISCONNECTED)) {
           connected = false;
           connectionState.setText("disconnected");
           connectButton.setText("connect");
           gattServicesList.setAdapter((SimpleExpandableListAdapter)null);
           dataField.setText("No Data");
           return;
         } 

        if (BluetoothLeService.ACTION_SERVICES_DISCOVERED.equals(action)){ 
          // show all the supported services and characteristics
          List<BluetoothGattService> L = 
                            bleService.getSupportedGattServices();
          if (!displayGattServices(L))
          { MyDialog  dialog = new MyDialog(BluetoothControlActivity.this);
            dialog.setTitle(deviceName);
            dialog.setMessage("No Heartrate Monitor");

            dialog.setPositiveButton("Continue",
               new DialogInterface.OnClickListener() {
                  public void onClick(DialogInterface d, int which) {
                          finish();
                  }
            });

           dialog.setOnCancelListener(
               new DialogInterface.OnCancelListener() {
                 public void onCancel(DialogInterface d) {
                          finish();
                  }
            });
         
                     
            dialog.show();
          }
          return;
         } 

        if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
           String d = intent.getStringExtra(BluetoothLeService.EXTRA_DATA);
           dataField.setText(d);
        }
      }

  };

  /* If a given GATT characteristic is selected, check for supported features.       This sample demonstrates 'Read' and 'Notify' features.  See
     http://d.android.com/reference/android/bluetooth/BluetoothGatt.html 
     for the complete list of supported characteristic features.
  */

   void setNotification(BluetoothGattCharacteristic characteristic)
   {
     final UUID uuid = characteristic.getUuid();
     final int perm = characteristic.getPermissions();
     final int prop = characteristic.getProperties();
/*
     showToast(uuid.toString() + "\nprop = " + prop + "\nperm = " + perm);
*/

/*
     if ((prop & BluetoothGattCharacteristic.PROPERTY_READ) != 0)
     { // If there is an active notification on a 
       // characteristic, clear it first so it doesn't 
       // update the data field on the user interface.

       if (notifyCharacteristic != null) {
         //showToast("Clear Notification");
         bleService.stopNotification(notifyCharacteristic);
         notifyCharacteristic = null;
       }

       bleService.readCharacteristic(characteristic);
     }
*/

     if ((prop & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0)
     { bleService.startNotification(characteristic);
       notifyCharacteristic = characteristic;
      }
     else
     { if (notifyCharacteristic != null)
              bleService.stopNotification(notifyCharacteristic);
       notifyCharacteristic = null;
      }
   }




  void showToast(String txt) { 
     Toast.makeText(this,txt,Toast.LENGTH_LONG).show();
  }

  @Override
  public void onCreate(Bundle savedInstanceState) 
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.ble_control);

    final Intent intent = getIntent();

    deviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
    deviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);

    getActionBar().setTitle(deviceName);

    ((TextView)findViewById(R.id.device_address)).setText(deviceAddress);
    connectButton = ((Button)findViewById(R.id.connect_button));

    connectButton.setOnClickListener(new OnClickListener() {
        @Override public void onClick(View v) { 
           if (connected)
              bleService.disconnect();
           else
              bleService.connect(deviceAddress,0);
        }
    });


    gattServicesList= (ExpandableListView)findViewById(R.id.gatt_services_list);
    gattServicesList.setOnChildClickListener(
       new ExpandableListView.OnChildClickListener() {
         @Override
         public boolean onChildClick(ExpandableListView parent, View v, 
                                     int groupPos,int childPos,long id) 
        { if (gattCharacteristics == null) return false;
          BluetoothGattCharacteristic characteristic =
                    gattCharacteristics.get(groupPos).get(childPos);
          setNotification(characteristic);
          return true; 
         }
    });


    connectionState = (TextView) findViewById(R.id.connection_state);
    dataField = (TextView) findViewById(R.id.data_value);

    final IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(BluetoothLeService.ACTION_CONNECTED);
    intentFilter.addAction(BluetoothLeService.ACTION_DISCONNECTED);
    intentFilter.addAction(BluetoothLeService.ACTION_SERVICES_DISCOVERED);
    intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);

    Log.i(TAG,"registerReceiver");
    registerReceiver(gattUpdateReceiver, intentFilter);

    Log.i(TAG,"bindService");
    Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
    bindService(gattServiceIntent, serviceConnection, BIND_AUTO_CREATE);
  }

  @Override
  protected void onResume() {
   super.onResume();
  }

  @Override
  protected void onPause() {
      super.onPause();
  }

  @Override
  protected void onDestroy() {
      super.onDestroy();
      unregisterReceiver(gattUpdateReceiver);
      unbindService(serviceConnection);
  }


 // Demonstrates how to iterate through the supported GATT 
 // Services/Characteristics.  In this sample, we populate 
 // the data structure that is bound to the ExpandableListView
 // on the UI.

  private boolean displayGattServices(List<BluetoothGattService> gattServices) 
  {
      if (gattServices == null) return false;

      ArrayList<HashMap<String,String>> gattServiceData = 
                                   new ArrayList<HashMap<String, String>>();

      ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData = 
                        new ArrayList<ArrayList<HashMap<String, String>>>();

      gattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();

      // Loops through available GATT Services.

/*
       BluetoothGattCharacteristic hrate_characteristic = null;
*/

      for (BluetoothGattService gattService : gattServices) 
      {
        HashMap<String, String> currentServiceData = new HashMap<String, String>();
        String uuid = gattService.getUuid().toString();
        String name = AllGattServices.lookup(uuid);

        //if (!name.equals("Heart Rate")) continue;

        currentServiceData.put(LIST_NAME, name);
        currentServiceData.put(LIST_UUID, uuid);
        gattServiceData.add(currentServiceData);

        ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
                  new ArrayList<HashMap<String,String>>();

        List<BluetoothGattCharacteristic> gattCharacteristicsList =
                  gattService.getCharacteristics();

        ArrayList<BluetoothGattCharacteristic> charas =
                  new ArrayList<BluetoothGattCharacteristic>();

        // Loops through available Characteristics.
        for (BluetoothGattCharacteristic ch : gattCharacteristicsList) 
        { charas.add(ch);


          HashMap<String, String> currentCharaData = new HashMap<String, String>();
          uuid = ch.getUuid().toString();
          name = AllGattCharacteristics.lookup(uuid);

          //if (name.equals("Heart Rate Measurement")) hrate_characteristic = ch;

          currentCharaData.put(LIST_NAME,name);
          currentCharaData.put(LIST_UUID, uuid);
          gattCharacteristicGroupData.add(currentCharaData);
         }

        gattCharacteristics.add(charas);
        gattCharacteristicData.add(gattCharacteristicGroupData);
      }

/*
      if (hrate_characteristic != null) {
        showToast("Blutooth: Connect"); 
        setNotification(hrate_characteristic);
      }
*/

      SimpleExpandableListAdapter gattServiceAdapter = 
         new SimpleExpandableListAdapter(
              this,
              gattServiceData,
              android.R.layout.simple_expandable_list_item_2,
              new String[] {LIST_NAME, LIST_UUID},
              new int[] { android.R.id.text1, android.R.id.text2 },
              gattCharacteristicData,
              android.R.layout.simple_expandable_list_item_2,
              new String[] {LIST_NAME, LIST_UUID},
              new int[] { android.R.id.text1, android.R.id.text2 }
        );

     gattServicesList.setAdapter(gattServiceAdapter);

     return true;
  }

}
