private void loadExerciseData() {
    final List<Routine> routines = DataManager.getCurrentPatient().getRoutines();

    // no routines to get data for, proceed to landing screen
    if (routines.isEmpty()) {
      dataIsAvailable();
    }

    for (final Routine routine : routines) {
      WLProcedureCaller wlProcedureCaller =
          new WLProcedureCaller("HealthcareAdapter", "getExercisesForRoutine");
      Object[] params = new Object[] {routine.getId()};
      wlProcedureCaller.invoke(
          params,
          new WLResponseListener() {
            @Override
            public void onSuccess(final WLResponse wlResponse) {
              runOnUiThread(
                  new Runnable() {
                    @Override
                    public void run() {
                      Exercise[] exercises = getExercisesFromJson(wlResponse.getResponseJSON());
                      DataManager.getCurrentPatient()
                          .addExercises(routine, Arrays.asList(exercises));

                      // check to see if all exercise data has been retrieved
                      int exerciseSets = DataManager.getCurrentPatient().getNumberOfExerciseSets();
                      if (exerciseSets == routines.size()) {
                        dataIsAvailable();
                      }
                    }
                  });
            }

            @Override
            public void onFailure(WLFailResponse wlFailResponse) {
              Log.i(TAG, "Could not load exercise data!");

              runOnUiThread(
                  new Runnable() {
                    @Override
                    public void run() {
                      dataIsAvailable();
                    }
                  });
            }
          });
    }
  }
  private void loadRoutineData() {
    WLProcedureCaller wlProcedureCaller = new WLProcedureCaller("HealthcareAdapter", "getRoutines");
    wlProcedureCaller.invoke(
        null,
        new WLResponseListener() {
          @Override
          public void onSuccess(WLResponse wlResponse) {
            Routine[] routines = getRoutinesFromJson(wlResponse.getResponseJSON());
            DataManager.getCurrentPatient().setRoutines(Arrays.asList(routines));
            loadExerciseData();
          }

          @Override
          public void onFailure(WLFailResponse wlFailResponse) {
            Log.i(TAG, "Could not load routine data!");
            loadExerciseData();
          }
        });
  }
  private void loadFormData() {
    WLProcedureCaller wlProcedureCaller =
        new WLProcedureCaller("HealthcareAdapter", "getQuestionnaireForUser");
    wlProcedureCaller.invoke(
        null,
        new WLResponseListener() {
          @Override
          public void onSuccess(WLResponse wlResponse) {
            Form[] forms = getFormsFromJson(wlResponse.getResponseJSON());
            DataManager.getCurrentPatient().setForms(Arrays.asList(forms));
            loadRoutineData();
          }

          @Override
          public void onFailure(WLFailResponse wlFailResponse) {
            Log.i(TAG, "Could not load form data!");
            loadRoutineData();
          }
        });
  }
  /**
   * Acts as the onClickListener for the login button (set in the activity's XML layout file). It
   * can also be invoked from the soft keyboard on the device. It sends the input entered by the
   * user for patient ID and password to the DataManager for validation. It also passes a callback
   * to handle the result of the login attempt. A valid login causes the LandingActivity to launch,
   * while an invalid login will notify the user that either the patient ID or password was invalid.
   *
   * @param view This is either the login button if the user clicks on the login button directly or
   *     the TextView of the password EditText if the user clicks "Done" on the soft keyboard.
   * @see com.ibm.mil.readyapps.physio.datamanager.DataManager
   * @see com.ibm.mil.readyapps.physio.activities.LandingActivity
   */
  public void submitLogin(View view) {
    mProgressDialog.show();

    // extract login input
    String patientId = mPatientText.getText().toString();
    String password = mPasswordText.getText().toString();
    String locale = getResources().getConfiguration().locale.toString();

    WLProcedureCaller wlProcedureCaller =
        new WLProcedureCaller("HealthcareAdapter", "submitAuthentication");
    Object[] params = new Object[] {patientId, password, locale};
    wlProcedureCaller.invoke(
        params,
        new WLResponseListener() {
          @Override
          public void onSuccess(final WLResponse wlResponse) {
            runOnUiThread(
                new Runnable() {
                  @Override
                  public void run() {
                    ProgressFragment.clearData();
                    if (!injectGoogleFitData()) {
                      loadUserData();
                    }
                  }
                });
          }

          @Override
          public void onFailure(WLFailResponse wlFailResponse) {
            runOnUiThread(
                new Runnable() {
                  @Override
                  public void run() {
                    mProgressDialog.dismiss();
                    showFailureDialog();
                  }
                });
          }
        });
  }
  private void loadUserData() {
    WLProcedureCaller wlProcedureCaller =
        new WLProcedureCaller("HealthcareAdapter", "getUserObject");
    wlProcedureCaller.invoke(
        null,
        new WLResponseListener() {
          @Override
          public void onSuccess(WLResponse wlResponse) {
            Patient currentPatient = new Patient(wlResponse.getResponseJSON());
            DataManager dataManager = DataManager.getInstance();
            dataManager.setCurrentPatient(currentPatient);
            loadFormData();
          }

          @Override
          public void onFailure(WLFailResponse wlFailResponse) {
            Log.i(TAG, "Could not load user data!");
            dataIsAvailable();
          }
        });
  }
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);

    Configuration configuration =
        new Configuration.Builder(this)
            .withAPIKey(APP_KEY)
            .withMode(Mode.QA)
            .withReportOnShakeEnabled(true)
            .build();

    Apphance.startNewSession(LoginActivity.this, configuration);

    fitClient = HealthDataRetriever.getClient(this);
    if (!fitClient.isConnected()) {
      fitClient.connect();
    }

    mPatientText = (EditText) findViewById(R.id.patient_id);
    mPasswordText = (EditText) findViewById(R.id.password);
    Button loginButton = (Button) findViewById(R.id.login_button);
    TextView loginTitle = (TextView) findViewById(R.id.login_title);

    mProgressDialog = AndroidUtils.circularProgressDialog(this);

    // set custom type faces for necessary views
    Typeface robotoThin = AndroidUtils.robotoThin(this);
    Typeface robotoBold = AndroidUtils.robotoBold(this);
    mPatientText.setTypeface(robotoThin);
    mPasswordText.setTypeface(robotoThin);
    loginButton.setTypeface(robotoThin);
    loginTitle.setTypeface(robotoBold);

    // route soft keyboard login completion to submitLogin listener
    mPasswordText.setOnEditorActionListener(
        new TextView.OnEditorActionListener() {
          @Override
          public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
            boolean handled = false;
            if (actionId == EditorInfo.IME_ACTION_DONE) {
              submitLogin(v);
              handled = true;
            }
            return handled;
          }
        });

    // connect to WL and register challenge handler for authentication
    WLClient wlClient = WLClient.createInstance(this);
    wlClient.connect(
        new WLResponseListener() {
          @Override
          public void onSuccess(WLResponse wlResponse) {
            Log.i(TAG, "Connected to Worklight!");
          }

          @Override
          public void onFailure(WLFailResponse wlFailResponse) {
            Log.i(TAG, "Could not connect to Worklight!");
          }
        },
        WLProcedureCaller.defaultOptions());
    wlClient.registerChallengeHandler(new ReadyAppsChallengeHandler(this, "SingleStepAuthRealm"));
  }