content: package com.adafruit.bluefruit.le.connect.app;
  
  import android.app.AlertDialog;
  import android.bluetooth.le.AdvertiseCallback;
  import android.content.Context;
  import android.graphics.drawable.Drawable;
  import android.os.Bundle;
  import android.text.Editable;
  import android.text.TextWatcher;
  import android.util.Log;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import android.view.WindowManager;
  import android.widget.EditText;
  import android.widget.TextView;
  
  import androidx.annotation.NonNull;
  import androidx.annotation.Nullable;
  import androidx.appcompat.widget.SwitchCompat;
  import androidx.core.content.ContextCompat;
  import androidx.fragment.app.Fragment;
  import androidx.fragment.app.FragmentActivity;
  import androidx.fragment.app.FragmentManager;
  import androidx.fragment.app.FragmentTransaction;
  import androidx.lifecycle.ViewModelProvider;
  import androidx.recyclerview.widget.DividerItemDecoration;
  import androidx.recyclerview.widget.LinearLayoutManager;
  import androidx.recyclerview.widget.RecyclerView;
  
  import com.adafruit.bluefruit.le.connect.R;
  import com.adafruit.bluefruit.le.connect.ble.peripheral.PeripheralService;
  import com.adafruit.bluefruit.le.connect.models.PeripheralModeViewModel;
  import com.adafruit.bluefruit.le.connect.utils.DialogUtils;
  import com.adafruit.bluefruit.le.connect.utils.LocalizationManager;
  
  public class PeripheralModeFragment extends Fragment {
      // Constants
      private final static String TAG = PeripheralModeFragment.class.getSimpleName();
      //private final static int kRssiRefreshInterval = 300; // in milliseconds
  
      // UI
      private RecyclerView mRecyclerView;
  
      // region Fragment lifecycle
      public static PeripheralModeFragment newInstance() {
          return new PeripheralModeFragment();
      }
  
      public PeripheralModeFragment() {
          // Required empty public constructor
      }
  
      @Override
      public void onAttach(@NonNull Context context) {
          super.onAttach(context);
      }
  
      @Override
      public void onDetach() {
          super.onDetach();
      }
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
  
          // Retain this fragment across configuration changes
          setRetainInstance(true);
      }
  
      @Override
      public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
          // Inflate the layout for this fragment
          return inflater.inflate(R.layout.fragment_peripheralmode, container, false);
      }
  
      @Override
      public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
          super.onViewCreated(view, savedInstanceState);
  
          final Context context = getContext();
          if (context != null) {
  
              // Peripherals recycler view
              mRecyclerView = view.findViewById(R.id.recyclerView);
              DividerItemDecoration itemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL);
              Drawable lineSeparatorDrawable = ContextCompat.getDrawable(context, R.drawable.simpledivideritemdecoration);
              assert lineSeparatorDrawable != null;
              itemDecoration.setDrawable(lineSeparatorDrawable);
              mRecyclerView.addItemDecoration(itemDecoration);
  
              //   recyclerView.setHasFixedSize(true);        // Improve performance
              RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
              mRecyclerView.setLayoutManager(layoutManager);
          }
      }
  
      @Override
      public void onActivityCreated(@Nullable Bundle savedInstanceState) {
          super.onActivityCreated(savedInstanceState);
  
          // ViewModel
          FragmentActivity activity = getActivity();
          if (activity != null) {
              //PeripheralModeViewModel model = new ViewModelProvider(activity).get(PeripheralModeViewModel.class);
              PeripheralModeViewModel model = new ViewModelProvider(activity, new ViewModelProvider.AndroidViewModelFactory(activity.getApplication())).get(PeripheralModeViewModel.class);
  
              model.getStartAdvertisingErrorCode().observe(getViewLifecycleOwner(), errorCode -> {
                  Log.d(TAG, "Advertising error: " + errorCode);
  
                  if (errorCode != null) {
                      int messageId = errorCode == AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE ? R.string.peripheral_advertising_starterror_toolarge : R.string.peripheral_advertising_starterror_undefined;
  
                      AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
                      AlertDialog dialog = builder.setTitle(R.string.dialog_error).setMessage(messageId)
                              .setPositiveButton(android.R.string.ok, null)
                              .show();
                      DialogUtils.keepDialogOnOrientationChanges(dialog);
                  }
              });
  
              // RecyclerView Adapter
              PeripheralModeAdapter adapter = new PeripheralModeAdapter(activity, model, index -> {
                  FragmentActivity activity2 = getActivity();
                  if (activity2 != null) {
                      FragmentManager fragmentManager = activity2.getSupportFragmentManager();
  
                      Fragment fragment = null;
                      String fragmentTag = null;
                      switch (index) {
                          case 0:
                              fragment = DeviceInformationServiceFragment.newInstance();
                              fragmentTag = "DeviceInformationService";
                              break;
                          case 1:
  
                              fragment = UartServiceFragment.newInstance();
                              fragmentTag = "UartService";
                              break;
                      }
  
                      if (fragment != null) {
                          FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()
                                  .setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right, R.anim.slide_in_right, R.anim.slide_out_left)
                                  .replace(R.id.contentLayout, fragment, fragmentTag);
                          fragmentTransaction.addToBackStack(null);
                          fragmentTransaction.commit();
                      }
  
                  }
              });
              mRecyclerView.setAdapter(adapter);
          }
      }
  
      @Override
      public void onResume() {
          super.onResume();
  
          FragmentActivity activity = getActivity();
          if (activity != null) {
              activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
          }
      }
  
      // endregion
  
      private static class PeripheralModeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
          // Constants
          private static final int kCellType_SectionTitle = 0;
          private static final int kCellType_AdvertisingInfoCell = 1;
          private static final int kCellType_ServicesCell = 2;
  
          private static final int kAdvertisingCellsStartPosition = 1;
          private static final int kServiceCellsStartPosition = 3;
  
          interface Listener {
              void onServiceSelected(int index);
          }
  
          // Structs
          static class SectionViewHolder extends RecyclerView.ViewHolder {
              TextView titleTextView;
  
              SectionViewHolder(View view) {
                  super(view);
                  titleTextView = view.findViewById(R.id.titleTextView);
              }
          }
  
          static class AdvertisingInfoViewHolder extends RecyclerView.ViewHolder {
              TextView titleTextView;
              EditText nameEditText;
              SwitchCompat enabledSwitch;
  
              AdvertisingInfoViewHolder(View view) {
                  super(view);
                  titleTextView = view.findViewById(R.id.titleTextView);
                  nameEditText = view.findViewById(R.id.nameEditText);
                  enabledSwitch = view.findViewById(R.id.enabledSwitch);
              }
          }
  
          static class ServiceViewHolder extends RecyclerView.ViewHolder {
              ViewGroup mainViewGroup;
              TextView nameTextView;
              SwitchCompat enabledSwitch;
  
              ServiceViewHolder(View view) {
                  super(view);
                  mainViewGroup = view.findViewById(R.id.mainViewGroup);
                  nameTextView = view.findViewById(R.id.nameTextView);
                  enabledSwitch = view.findViewById(R.id.enabledSwitch);
              }
          }
  
          // Data
          private final Context mContext;
          private final PeripheralModeViewModel mModel;
          private final Listener mListener;
  
          //
          PeripheralModeAdapter(@NonNull Context context, @NonNull PeripheralModeViewModel viewModel, @NonNull Listener listener) {
              mContext = context;
              mModel = viewModel;
              mListener = listener;
          }
  
          @Override
          public int getItemViewType(int position) {
              super.getItemViewType(position);
  
              if (position == kAdvertisingCellsStartPosition - 1 || position == kServiceCellsStartPosition - 1) {
                  return kCellType_SectionTitle;
              } else if (position == kCellType_AdvertisingInfoCell) {
                  return kCellType_AdvertisingInfoCell;
              } else {
                  return kCellType_ServicesCell;
              }
          }
  
          // Create new views (invoked by the layout manager)
          @NonNull
          @Override
          public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
              //Log.d(TAG, "onCreateViewHolder type: " + viewType);
              switch (viewType) {
                  case kCellType_SectionTitle: {
                      View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_common_section_item, parent, false);
                      return new SectionViewHolder(view);
                  }
                  case kCellType_AdvertisingInfoCell: {
                      View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_peripheralmode_name_item, parent, false);
                      return new AdvertisingInfoViewHolder(view);
                  }
                  case kCellType_ServicesCell: {
                      View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_common_switch_item, parent, false);
                      return new ServiceViewHolder(view);
                  }
                  default: {
                      Log.e(TAG, "Unknown cell type");
                      throw new AssertionError("Unknown cell type");
                  }
              }
          }
  
          // Replace the contents of a view (invoked by the layout manager)
          @Override
          public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) {
  
              LocalizationManager localizationManager = LocalizationManager.getInstance();
              final int viewType = getItemViewType(position);
              switch (viewType) {
                  case kCellType_SectionTitle:
                      SectionViewHolder sectionViewHolder = (SectionViewHolder) holder;
                      sectionViewHolder.titleTextView.setText(localizationManager.getString(mContext, position == kAdvertisingCellsStartPosition - 1 ? "peripheral_advertisinginfo" : "peripheral_services"));
                      break;
  
                  case kCellType_AdvertisingInfoCell:
                      AdvertisingInfoViewHolder advertisingInfoViewHolder = (AdvertisingInfoViewHolder) holder;
                      advertisingInfoViewHolder.titleTextView.setText(R.string.peripheral_localname);
  
                      final String localName = mModel.getLocalName();
                      advertisingInfoViewHolder.nameEditText.setText(localName);
                      advertisingInfoViewHolder.nameEditText.setHint(localName);
                      advertisingInfoViewHolder.nameEditText.addTextChangedListener(new TextWatcher() {
  
                          public void afterTextChanged(Editable s) {
                              String text = s.toString();
                              mModel.setLocalName(mContext, text);
                          }
  
                          public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                          }
  
                          public void onTextChanged(CharSequence s, int start, int before, int count) {
                          }
                      });
  
                      advertisingInfoViewHolder.enabledSwitch.setChecked(mModel.isIncludingDeviceName(mContext));
                      advertisingInfoViewHolder.enabledSwitch.setOnCheckedChangeListener((compoundButton, b) -> {
                          if (compoundButton.isPressed()) {
                              mModel.setIncludeDeviceName(mContext, b);
                          }
                      });
  
                      break;
  
                  case kCellType_ServicesCell:
                      final int servicePosition = position - kServiceCellsStartPosition;
                      ServiceViewHolder serviceViewHolder = (ServiceViewHolder) holder;
                      final PeripheralService service = mModel.getPeripheralServices().get(servicePosition);
                      serviceViewHolder.enabledSwitch.setChecked(service.isEnabled());
                      serviceViewHolder.enabledSwitch.setOnCheckedChangeListener((compoundButton, b) -> {
                          if (compoundButton.isPressed()) {
                              service.setEnabled(mContext, b);
                              mModel.start(mContext);     // Force re-start advertising
                          }
                      });
                      serviceViewHolder.nameTextView.setText(service.getName());
                      serviceViewHolder.mainViewGroup.setOnClickListener(view -> mListener.onServiceSelected(servicePosition));
                      break;
  
                  default:
                      Log.e(TAG, "Unknown cell type");
                      break;
              }
          }
  
          // Return the size of your dataset (invoked by the layout manager)
          @Override
          public int getItemCount() {
              return 1 + 1 + 1 + mModel.getPeripheralServices().size();
          }
      }
  }