/**
   * Compares {@code pattern} to the given pattern ( {@link #ACTION_COMPARE_PATTERN}) or to the
   * generated "CAPTCHA" pattern ( {@link #ACTION_VERIFY_CAPTCHA}). Then finishes the activity if
   * they match.
   *
   * @param pattern the pattern to be compared.
   */
  private void doComparePattern(final List<Cell> pattern) {
    if (pattern == null) return;

    /*
     * Use a LoadingView because decrypting pattern might take time...
     */

    mLoadingView =
        new LoadingView<Void, Void, Object>(this, mViewGroupProgressBar) {

          @Override
          protected Object doInBackground(Void... params) {
            if (ACTION_COMPARE_PATTERN.equals(getIntent().getAction())) {
              char[] currentPattern = getIntent().getCharArrayExtra(EXTRA_PATTERN);
              if (currentPattern == null)
                currentPattern = Settings.Security.getPattern(LockPatternActivity.this);
              if (currentPattern != null) {
                if (mEncrypter != null)
                  return pattern.equals(
                      mEncrypter.decrypt(LockPatternActivity.this, currentPattern));
                else
                  return Arrays.equals(
                      currentPattern, LockPatternUtils.patternToSha1(pattern).toCharArray());
              }
            } // ACTION_COMPARE_PATTERN
            else if (ACTION_VERIFY_CAPTCHA.equals(getIntent().getAction())) {
              return pattern.equals(getIntent().getParcelableArrayListExtra(EXTRA_PATTERN));
            } // ACTION_VERIFY_CAPTCHA

            return false;
          } // doInBackground()

          @Override
          protected void onPostExecute(Object result) {
            super.onPostExecute(result);

            if ((Boolean) result) finishWithResultOk(null);
            else {
              mRetryCount++;
              mIntentResult.putExtra(EXTRA_RETRY_COUNT, mRetryCount);

              if (mRetryCount >= mMaxRetries) finishWithNegativeResult(RESULT_FAILED);
              else {
                mLockPatternView.setDisplayMode(DisplayMode.Wrong);
                mTextInfo.setText(
                    com.haibison.android.lockpattern.R.string.alp_42447968_msg_try_again);
                mLockPatternView.postDelayed(
                    mLockPatternViewReloader, DELAY_TIME_TO_RELOAD_LOCK_PATTERN_VIEW);
              }
            }
          } // onPostExecute()
        };

    mLoadingView.execute();
  } // doComparePattern()
  @Override
  public boolean onKeyDown(int keyCode, KeyEvent event) {
    /*
     * Use this hook instead of onBackPressed(), because onBackPressed() is
     * not available in API 4.
     */
    if (keyCode == KeyEvent.KEYCODE_BACK
        && ACTION_COMPARE_PATTERN.equals(getIntent().getAction())) {
      if (mLoadingView != null) mLoadingView.cancel(true);

      finishWithNegativeResult(RESULT_CANCELED);

      return true;
    } // if

    return super.onKeyDown(keyCode, event);
  } // onKeyDown()
  /**
   * Checks and creates the pattern.
   *
   * @param pattern the current pattern of lock pattern view.
   */
  private void doCheckAndCreatePattern(final List<Cell> pattern) {
    if (pattern.size() < mMinWiredDots) {
      mLockPatternView.setDisplayMode(DisplayMode.Wrong);
      mTextInfo.setText(
          getResources()
              .getQuantityString(
                  com.haibison.android.lockpattern.R.plurals.alp_42447968_pmsg_connect_x_dots,
                  mMinWiredDots,
                  mMinWiredDots));
      mLockPatternView.postDelayed(
          mLockPatternViewReloader, DELAY_TIME_TO_RELOAD_LOCK_PATTERN_VIEW);
      return;
    } // if

    if (getIntent().hasExtra(EXTRA_PATTERN)) {
      /*
       * Use a LoadingView because decrypting pattern might take time...
       */
      mLoadingView =
          new LoadingView<Void, Void, Object>(this, mViewGroupProgressBar) {

            @Override
            protected Object doInBackground(Void... params) {
              if (mEncrypter != null)
                return pattern.equals(
                    mEncrypter.decrypt(
                        LockPatternActivity.this, getIntent().getCharArrayExtra(EXTRA_PATTERN)));
              else
                return Arrays.equals(
                    getIntent().getCharArrayExtra(EXTRA_PATTERN),
                    LockPatternUtils.patternToSha1(pattern).toCharArray());
            } // doInBackground()

            @Override
            protected void onPostExecute(Object result) {
              super.onPostExecute(result);

              if ((Boolean) result) {
                mTextInfo.setText(
                    com.haibison
                        .android
                        .lockpattern
                        .R
                        .string
                        .alp_42447968_msg_your_new_unlock_pattern);
                mBtnConfirm.setEnabled(true);
              } else {
                mTextInfo.setText(
                    com.haibison
                        .android
                        .lockpattern
                        .R
                        .string
                        .alp_42447968_msg_redraw_pattern_to_confirm);
                mBtnConfirm.setEnabled(false);
                mLockPatternView.setDisplayMode(DisplayMode.Wrong);
                mLockPatternView.postDelayed(
                    mLockPatternViewReloader, DELAY_TIME_TO_RELOAD_LOCK_PATTERN_VIEW);
              }
            } // onPostExecute()
          };

      mLoadingView.execute();
    } else {
      /*
       * Use a LoadingView because encrypting pattern might take time...
       */
      mLoadingView =
          new LoadingView<Void, Void, Object>(this, mViewGroupProgressBar) {

            @Override
            protected Object doInBackground(Void... params) {
              return mEncrypter != null
                  ? mEncrypter.encrypt(LockPatternActivity.this, pattern)
                  : LockPatternUtils.patternToSha1(pattern).toCharArray();
            } // onCancel()

            @Override
            protected void onPostExecute(Object result) {
              super.onPostExecute(result);

              getIntent().putExtra(EXTRA_PATTERN, (char[]) result);
              mTextInfo.setText(
                  com.haibison.android.lockpattern.R.string.alp_42447968_msg_pattern_recorded);
              mBtnConfirm.setEnabled(true);
            } // onPostExecute()
          };

      mLoadingView.execute();
    }
  } // doCheckAndCreatePattern()
  @Override
  protected void onDestroy() {
    if (mLoadingView != null) mLoadingView.cancel(true);

    super.onDestroy();
  } // onDestroy()